From 6cd1cee328f8ab645ed4bf6a10483b38f6464e18 Mon Sep 17 00:00:00 2001 From: colin Date: Mon, 20 Jun 2011 20:46:41 +0000 Subject: [PATCH] Merging from nmap-exp/colin/nmap-addrset, nmap-exp/colin/nbase-addrset, and /nmap-exp/colin/ncat-addrset Ported addrset from ncat to nbase. Made --exclude and --exclude-file options use addrset. As a side effect IPv6 Excludes work. --- nmap.cc | 22 +++---- targets.cc | 166 +++++++---------------------------------------------- targets.h | 9 ++- 3 files changed, 33 insertions(+), 164 deletions(-) diff --git a/nmap.cc b/nmap.cc index e6bb5e952..5dc4a0d07 100644 --- a/nmap.cc +++ b/nmap.cc @@ -475,7 +475,7 @@ int nmap_main(int argc, char *argv[]) { /* Only NSE scripts can add targets */ NewTargets *new_targets = NULL; #endif - TargetGroup *exclude_group = NULL; + addrset exclude_group; char myname[MAXHOSTNAMELEN + 1]; #if (defined(IN_ADDR_DEEPSTRUCT) || defined( SOLARIS)) /* Note that struct in_addr in solaris is 3 levels deep just to store an @@ -1645,20 +1645,17 @@ int nmap_main(int argc, char *argv[]) { /* lets load our exclude list */ if (excludefd != NULL) { - exclude_group = load_exclude_file(excludefd); + load_exclude_file(&exclude_group, excludefd); fclose(excludefd); } if (exclude_spec != NULL) { /* Simultaneous --excludefile and --exclude are not supported. */ - assert(exclude_group == NULL); - exclude_group = load_exclude_string(exclude_spec); + load_exclude_string(&exclude_group ,exclude_spec); free(exclude_spec); } - if (exclude_group != NULL) { - if (o.debugging > 3) - dumpExclude(exclude_group); - } + if (o.debugging > 3) + dumpExclude(&exclude_group); #ifndef NOLUA if (o.scriptupdatedb) { @@ -1692,7 +1689,7 @@ int nmap_main(int argc, char *argv[]) { ideal_scan_group_sz = determineScanGroupSize(o.numhosts_scanned, &ports); while(Targets.size() < ideal_scan_group_sz) { o.current_scantype = HOST_DISCOVERY; - currenths = nexthost(hstate, exclude_group, &ports, o.pingtype); + currenths = nexthost(hstate, &exclude_group, &ports, o.pingtype); if (!currenths) { /* Try to refill with any remaining expressions */ /* First free the old ones */ @@ -1730,7 +1727,7 @@ int nmap_main(int argc, char *argv[]) { num_host_exp_groups); /* Try one last time -- with new expressions */ - currenths = nexthost(hstate, exclude_group, &ports, o.pingtype); + currenths = nexthost(hstate, &exclude_group, &ports, o.pingtype); if (!currenths) break; } @@ -1971,9 +1968,8 @@ int nmap_main(int argc, char *argv[]) { #endif delete hstate; - if (exclude_group) - delete[] exclude_group; - + + addrset_free(&exclude_group); hstate = NULL; /* Free host expressions */ diff --git a/targets.cc b/targets.cc index d1aa581bc..ed260c616 100644 --- a/targets.cc +++ b/targets.cc @@ -101,7 +101,6 @@ #include "nmap_dns.h" #include "nmap_tty.h" #include "utils.h" - using namespace std; extern NmapOps o; @@ -156,133 +155,40 @@ void returnhost(HostGroupState *hs) { /* Is the host passed as Target to be excluded? Much of this logic had to be rewritten from wam's original code to allow for the objects */ static int hostInExclude(struct sockaddr *checksock, size_t checksocklen, - TargetGroup *exclude_group) { - unsigned long tmpTarget; /* ip we examine */ - int i=0; /* a simple index */ - char targets_type; /* what is the address type of the Target Group */ - struct sockaddr_storage ss; - struct sockaddr_in *sin = (struct sockaddr_in *) &ss; - size_t slen; /* needed for funct but not used */ - unsigned long mask = 0; /* our trusty netmask, which we convert to nbo */ - struct sockaddr_in *checkhost_in; - - if ((TargetGroup *)0 == exclude_group) + const addrset *exclude_group) { + if (exclude_group == NULL) return 0; - checkhost_in = NULL; - if (checksock->sa_family == AF_INET) { - assert(checksocklen >= sizeof(struct sockaddr_in)); - checkhost_in = (struct sockaddr_in *) checksock; - } + if (checksock == NULL) + return 0; - /* First find out what type of addresses are in the target group */ - targets_type = exclude_group[i].get_targets_type(); - - /* Lets go through the targets until we reach our uninitialized placeholder */ - while (exclude_group[i].get_targets_type() != TargetGroup::TYPE_NONE) { - /* while there are still hosts in the target group */ - while (exclude_group[i].get_next_host(&ss, &slen) == 0) { - tmpTarget = sin->sin_addr.s_addr; - - /* For Netmasks simply compare the network bits and move to the next - * group if it does not compare, we don't care about the individual addrs */ - if (targets_type == TargetGroup::IPV4_NETMASK) { - if (checkhost_in == NULL) - break; - mask = htonl((unsigned long) (0-1) << (32-exclude_group[i].get_mask())); - if ((tmpTarget & mask) == (checkhost_in->sin_addr.s_addr & mask)) { - exclude_group[i].rewind(); - return 1; - } else { - break; - } - } - /* For ranges we need to be a little more slick, if we don't find a match - * we should skip the rest of the addrs in the octet, thank wam for this - * optimization */ - else if (targets_type == TargetGroup::IPV4_RANGES) { - if (checkhost_in == NULL) - break; - if (tmpTarget == checkhost_in->sin_addr.s_addr) { - exclude_group[i].rewind(); - return 1; - } else { - /* note these are in network byte order */ - if ((tmpTarget & 0x000000ff) != (checkhost_in->sin_addr.s_addr & 0x000000ff)) - exclude_group[i].skip_range(TargetGroup::FIRST_OCTET); - else if ((tmpTarget & 0x0000ff00) != (checkhost_in->sin_addr.s_addr & 0x0000ff00)) - exclude_group[i].skip_range(TargetGroup::SECOND_OCTET); - else if ((tmpTarget & 0x00ff0000) != (checkhost_in->sin_addr.s_addr & 0x00ff0000)) - exclude_group[i].skip_range(TargetGroup::THIRD_OCTET); - - continue; - } - } -#if HAVE_IPV6 - else if (targets_type == TargetGroup::IPV6_ADDRESS) { - fatal("exclude file not supported for IPV6 -- If it is important to you, send a mail to fyodor@insecure.org so I can guage support\n"); - } -#endif - } - exclude_group[i++].rewind(); - } - - /* we did not find the host */ + if (addrset_contains(exclude_group,checksock)) + return 1; return 0; } -/* Convert a vector of host specifications to an array (allocated with new[]) of - TargetGroups. The size of the returned array is one greater than the number - of host specs, to leave on uninitialized member at the end. */ -static TargetGroup *specs_to_targetgroups(const std::vector &specs) { - TargetGroup *excludelist; - unsigned int i; - - excludelist = new TargetGroup[specs.size() + 1]; - - for (i = 0; i < specs.size(); i++) { - if (excludelist[i].parse_expr(specs[i].c_str(), o.af()) == 0) { - if (o.debugging > 1) - error("Loaded exclude target of: %s", specs[i].c_str()); - } - } - - return excludelist; -} - /* Load an exclude list from a file for --excludefile. */ -TargetGroup* load_exclude_file(FILE *fp) { - std::vector specs; +int load_exclude_file(addrset *excludelist, FILE *fp) { + addrset_init(excludelist); char host_spec[1024]; size_t n; while ((n = read_host_from_file(fp, host_spec, sizeof(host_spec))) > 0) { if (n >= sizeof(host_spec)) fatal("One of your exclude file specifications was too long to read (>= %u chars)", (unsigned int) sizeof(host_spec)); - specs.push_back(host_spec); + addrset_add_spec(excludelist, host_spec, o.af(), 1); } - return specs_to_targetgroups(specs); + return 1; } /* Load a comma-separated exclude list from a string, the argument to --exclude. */ -TargetGroup* load_exclude_string(const char *s) { - std::vector specs; - const char *begin, *p; +int load_exclude_string(addrset *excludelist, const char *s) { + addrset_init(excludelist); + addrset_add_spec(excludelist, s, o.af(), 1); - p = s; - while (*p != '\0') { - begin = p; - while (*p != '\0' && *p != ',') - p++; - specs.push_back(std::string(begin, p - begin)); - if (*p == '\0') - break; - p++; - } - - return specs_to_targetgroups(specs); + return 1; } @@ -292,43 +198,11 @@ TargetGroup* load_exclude_string(const char *s) { the Target Group Object. Rather than writing a bunch of methods to return private attributes, which would only be used for debugging, I went for the method below. */ -int dumpExclude(TargetGroup *exclude_group) { - int i=0, debug_save=0, type=TargetGroup::TYPE_NONE; - unsigned int mask = 0; - struct sockaddr_storage ss; - struct sockaddr_in *sin = (struct sockaddr_in *) &ss; - size_t slen; - - /* shut off debugging for now, this is a debug routine in itself, we don't - want to see all the debug messages inside of the object */ - debug_save = o.debugging; - o.debugging = 0; - - while ((type = exclude_group[i].get_targets_type()) != TargetGroup::TYPE_NONE) { - switch (type) { - case TargetGroup::IPV4_NETMASK: - exclude_group[i].get_next_host(&ss, &slen); - mask = exclude_group[i].get_mask(); - error("exclude host group %d is %s/%d", i, inet_ntoa(sin->sin_addr), mask); - break; - - case TargetGroup::IPV4_RANGES: - while (exclude_group[i].get_next_host(&ss, &slen) == 0) - error("exclude host group %d is %s", i, inet_ntoa(sin->sin_addr)); - break; - - case TargetGroup::IPV6_ADDRESS: - fatal("IPV6 addresses are not supported in the exclude file\n"); - break; - - default: - fatal("Unknown target type in exclude file.\n"); - } - exclude_group[i++].rewind(); - } - - /* return debugging to what it was */ - o.debugging = debug_save; +int dumpExclude(addrset *exclude_group) { + /* When we updated the exclude code to use addrset from libnetutil (originally + from ncat) there was no simple available debugging function. Thus we are + zeroing this and if it is needed look in addrset.cc for the lower level + debug function -Colin */ return 1; } @@ -415,7 +289,7 @@ static bool target_needs_new_hostgroup(const HostGroupState *hs, const Target *t return false; } -Target *nexthost(HostGroupState *hs, TargetGroup *exclude_group, +Target *nexthost(HostGroupState *hs, const addrset *exclude_group, struct scan_lists *ports, int pingtype) { int i; struct sockaddr_storage ss; diff --git a/targets.h b/targets.h index 4f00559a4..0c055a6c2 100644 --- a/targets.h +++ b/targets.h @@ -154,15 +154,14 @@ struct pingtech { rawprotoscan: 1; }; - /* Ports is the list of ports the user asked to be scanned (0 terminated), you can just pass NULL (it is only a stupid optimization that needs it) */ -Target *nexthost(HostGroupState *hs, TargetGroup *exclude_group, +Target *nexthost(HostGroupState *hs,const addrset *exclude_group, struct scan_lists *ports, int pingtype); -TargetGroup* load_exclude_file(FILE *fp); -TargetGroup* load_exclude_string(const char *s); +int load_exclude_file(addrset *exclude_group, FILE *fp); +int load_exclude_string(addrset *exclude_group, const char *s); /* a debugging routine to dump an exclude list to stdout. */ -int dumpExclude(TargetGroup*exclude_group); +int dumpExclude(addrset *exclude_group); /* Returns the last host obtained by nexthost. It will be given again the next time you call nexthost(). */ void returnhost(HostGroupState *hs);