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