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