From 61b976a45c8e6508217caf3252af26df32cdf7de Mon Sep 17 00:00:00 2001 From: fyodor Date: Mon, 4 Feb 2008 22:10:29 +0000 Subject: [PATCH] o Nmap now saves the target name (if any) specified on the command line, since this can differ from the reverse DNS results. It can be particularly important when doing HTTP tests against virtual hosts. The data can be accessed from target->HostName() from Nmap proper and host.targetname from NSE scripts. The NSE HTTP library now uses this for the Host header. Thanks to Sven Klemm for adding this useful feature. --- CHANGELOG | 8 ++++++++ Target.cc | 15 +++++++++++++++ Target.h | 11 +++++++++++ TargetGroup.cc | 2 +- TargetGroup.h | 4 ++++ docs/scripting.xml | 10 ++++++++++ nse_nmaplib.cc | 7 ++++++- nselib/http.lua | 2 +- targets.cc | 7 +++++++ 9 files changed, 63 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 89dc4b549..7d165a87d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,13 @@ # Nmap Changelog ($Id$); -*-text-*- +o Nmap now saves the target name (if any) specified on the command + line, since this can differ from the reverse DNS results. It can be + particularly important when doing HTTP tests against virtual hosts. + The data can be accessed from target->HostName() from Nmap proper + and host.targetname from NSE scripts. The NSE HTTP library now uses + this for the Host header. Thanks to Sven Klemm for adding this + useful feature. + o Added NSE HTTP library which allows scripts to easily fetch URLs with http.get_url() or create more complex requests with http.request(). There is also an http.get() function which takes diff --git a/Target.cc b/Target.cc index e6685fd6b..e5aff5205 100644 --- a/Target.cc +++ b/Target.cc @@ -119,6 +119,7 @@ Target::Target() { void Target::Initialize() { hostname = NULL; + targetname = NULL; memset(&seq, 0, sizeof(seq)); distance = -1; FPR1 = NULL; @@ -169,6 +170,9 @@ void Target::FreeInternal() { if (hostname) free(hostname); + if (targetname) + free(targetname); + if (nameIPBuf) { free(nameIPBuf); nameIPBuf = NULL; @@ -221,6 +225,7 @@ void Target::setTargetSockAddr(struct sockaddr_storage *ss, size_t ss_len) { /* We had an old target sock, so we better blow away the hostname as this one may be new. */ setHostName(NULL); + setTargetName(NULL); } memcpy(&targetsock, ss, ss_len); targetsocklen = ss_len; @@ -308,6 +313,16 @@ void Target::setHostName(char *name) { } } +void Target::setTargetName(char *name) { + if (targetname) { + free(targetname); + targetname = NULL; + } + if (name) { + targetname = strdup(name); + } +} + /* Generates a printable string consisting of the host's IP address and hostname (if available). Eg "www.insecure.org (64.71.184.53)" or "fe80::202:e3ff:fe14:1102". The name is diff --git a/Target.h b/Target.h index 417dbaee9..c0a32d684 100644 --- a/Target.h +++ b/Target.h @@ -176,6 +176,16 @@ class Target { /* This next version returns a STATIC buffer -- so no concurrency */ const char *NameIP(); + /* Give the name from the last setTargetName() call, which is the + name of the target given on the command line if it's a named + host. */ + const char *TargetName() { return targetname; } + /* You can set to NULL to erase a name. The targetname is blown + away when you setTargetSockAddr(), so make sure you do these in proper + order + */ + void setTargetName(char *name); + /* If the host is directly connected on a network, set and retrieve that information here. directlyConnected() will abort if it hasn't been set yet. */ @@ -246,6 +256,7 @@ class Target { unsigned int flags; /* HOST_UP, HOST_DOWN, HOST_FIREWALLED, HOST_BROADCAST (instead of HOST_BROADCAST use wierd_responses */ struct timeout_info to; char *hostname; // Null if unable to resolve or unset + char * targetname; // The name of the target host given on the commmand line if it is a named host #ifndef NOLUA ScriptResults scriptResults; diff --git a/TargetGroup.cc b/TargetGroup.cc index 50fe95f98..a1fee6de9 100644 --- a/TargetGroup.cc +++ b/TargetGroup.cc @@ -168,7 +168,7 @@ int TargetGroup::parse_expr(const char * const target_expr, int af) { char *hostexp = strdup(target_expr); struct hostent *target; unsigned long longtmp; - int namedhost = 0; + namedhost = 0; if (targets_type != TYPE_NONE) Initialize(); diff --git a/TargetGroup.h b/TargetGroup.h index d041c16bc..b398ddbb6 100644 --- a/TargetGroup.h +++ b/TargetGroup.h @@ -134,6 +134,8 @@ class TargetGroup { char get_targets_type() {return targets_type;}; /* get the netmask */ int get_mask() {return netmask;}; + /* is the current expression a named host */ + int get_namedhost() {return namedhost;}; /* Skip an octet in the range array */ int skip_range(_octet_nums octet); private: @@ -160,6 +162,8 @@ class TargetGroup { the fields are not valid */ unsigned long ipsleft; + // is the current target expression a named host + int namedhost; }; class HostGroupState { diff --git a/docs/scripting.xml b/docs/scripting.xml index c88d73591..1e1e7da50 100644 --- a/docs/scripting.xml +++ b/docs/scripting.xml @@ -1526,6 +1526,16 @@ if(s) code_to_be_done_on_match end + + + host.targetname + + Contains the name of the host as specified on the commandline. + If the target given on the commandline contains a netmask or is an IP + address the value of the field is nil. + + + host.directly_connected diff --git a/nse_nmaplib.cc b/nse_nmaplib.cc index 8f5d48678..0bd3f8cb7 100644 --- a/nse_nmaplib.cc +++ b/nse_nmaplib.cc @@ -180,7 +180,7 @@ void set_version(lua_State* l, struct serviceDeductions sd) { } } -/* set host ip and host name onto the +/* set host ip, host name and target name onto the * table which is currently on the stack * set name of the os run by the host onto the * table which is currently on the stack @@ -199,6 +199,11 @@ void set_hostinfo(lua_State* l, Target *currenths) { lua_pushstring(l, strncpy(hostname, currenths->HostName(), 1024)); lua_setfield(l, -2, "name"); + if ( currenths->TargetName() ) { // else nil + lua_pushstring(l, strncpy(hostname, currenths->TargetName(), 1024)); + lua_setfield(l, -2, "targetname"); + } + if(currenths->directlyConnectedOrUnset() != -1){ lua_pushboolean(l, currenths->directlyConnected()); lua_setfield(l, -2, "directly_connected"); diff --git a/nselib/http.lua b/nselib/http.lua index fb502a01e..2718d51b1 100644 --- a/nselib/http.lua +++ b/nselib/http.lua @@ -72,7 +72,7 @@ request = function( host, port, data, options ) options = options or {} if type(host) == 'table' then - host = ( host.name ~= '' and host.name ) or host.ip + host = host.targetname or ( host.name ~= '' and host.name ) or host.ip end local protocol = 'tcp' diff --git a/targets.cc b/targets.cc index db98c2451..f6d537aea 100644 --- a/targets.cc +++ b/targets.cc @@ -497,6 +497,13 @@ do { hs->hostbatch[hidx] = new Target(); hs->hostbatch[hidx]->setTargetSockAddr(&ss, sslen); + /* put target expression in target if we have a named host without netmask */ + if ( hs->current_expression.get_targets_type() == TargetGroup::IPV4_NETMASK && + hs->current_expression.get_namedhost() && + !strchr( hs->target_expressions[hs->next_expression-1], '/' ) ) { + hs->hostbatch[hidx]->setTargetName(hs->target_expressions[hs->next_expression-1]); + } + /* We figure out the source IP/device IFF 1) We are r00t AND 2) We are doing tcp or udp pingscan OR