diff --git a/CHANGELOG b/CHANGELOG
index c7ff9f050..0f698ab17 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,11 @@
# Nmap Changelog ($Id$); -*-text-*-
+o [NSE] The nmap.connect function can now accept host and port tables
+ (like those provided to the action function) in place of a string
+ and a number. The motivation behind this is to easily support Server
+ Name Indication for SSL sockets by reading host.targetname. [David
+ Fifield]
+
o [NSE] Added wdb-version, which discovers information from a VxWorks
debug service that is often left open. [Daniel Miller]
diff --git a/nse_nsock.cc b/nse_nsock.cc
index aeed77648..7c569128a 100644
--- a/nse_nsock.cc
+++ b/nse_nsock.cc
@@ -654,9 +654,54 @@ static int l_nsock_connect(lua_State * L)
static const char * const op[] = {"tcp", "udp", "ssl", NULL};
l_nsock_udata *udata = (l_nsock_udata *) luaL_checkudata(L, 1, "nsock");
- const char *addr = luaL_checkstring(L, 2);
- unsigned short port = (unsigned short) luaL_checkint(L, 3);
- int what = luaL_checkoption(L, 4, "tcp", op);
+ const char *addr, *targetname;
+ unsigned short port;
+ int what;
+
+ addr = NULL;
+ targetname = NULL;
+
+ /* host argument. */
+ if (lua_istable(L, 2)) {
+ const char *ip;
+
+ ip = NULL;
+ targetname = NULL;
+
+ lua_getfield(L, 2, "ip");
+ ip = lua_tostring(L, -1);
+ lua_pop(L, 1);
+
+ lua_getfield(L, 2, "targetname");
+ targetname = lua_tostring(L, -1);
+ lua_pop(L, 1);
+
+ if (ip != NULL)
+ addr = ip;
+ else if (targetname != NULL)
+ addr = targetname;
+ else
+ luaL_error(L, "host table does not have a 'ip' or 'targetname' field");
+ } else {
+ addr = luaL_checkstring(L, 2);
+ targetname = addr;
+ }
+
+ /* port argument. */
+ if (lua_istable(L, 3)) {
+ lua_getfield(L, 3, "number");
+ if (lua_isnil(L, -1))
+ luaL_error(L, "port table does not have a 'number' field");
+ else if (!lua_isnumber(L, -1))
+ luaL_error(L, "port.number is not numeric");
+ port = lua_tointeger(L, -1);
+ lua_pop(L, 1);
+ } else {
+ port = (unsigned short) luaL_checkint(L, 3);
+ }
+
+ /* proto argument. */
+ what = luaL_checkoption(L, 4, "tcp", op);
const char *error;
struct addrinfo *dest;
@@ -698,6 +743,10 @@ static int l_nsock_connect(lua_State * L)
o.SourceSockAddr(&ss, &sslen);
nsi_set_localaddr(udata->nsiod, &ss, sslen);
}
+ if (targetname != NULL) {
+ if (nsi_set_hostname(udata->nsiod, targetname) == -1)
+ fatal("nsi_set_hostname(\"%s\" failed in %s()", targetname, __func__);
+ }
if (o.ipoptionslen)
nsi_set_ipoptions(udata->nsiod, o.ipoptions, o.ipoptionslen);
diff --git a/nselib/nmap.luadoc b/nselib/nmap.luadoc
index 108b3f583..0cd94c01a 100644
--- a/nselib/nmap.luadoc
+++ b/nselib/nmap.luadoc
@@ -327,10 +327,18 @@ function bind(addr, port)
--- Establishes a connection.
--
-- This method puts a socket in a state ready for communication. It takes as
--- arguments a host descriptor (either an IP address or a hostname), a port
--- number and optionally a protocol. The protocol must be one of
--- "tcp", "udp" or "ssl"; it is
--- "tcp" if not specified.
+-- arguments a host descriptor (a host table, IP address, or hostname), a port
+-- descriptor (a port table or number), and optionally a protocol. If given, the
+-- protocol must be one of
+-- "tcp", "udp" or "ssl";
+-- "tcp" is the default.
+--
+-- If host is a host table, it must contain at least one of the
+-- keys addr or targetname. If targetname
+-- is given, it is used to request the correct certificate in SSL connections.
+-- Passing a string instead of a host table acts like host.addr and
+-- host.targetname were set to the same value. If port
+-- is a table, it must contain the number key.
--
-- On success the function returns a true value. On failure it returns a false
-- value (false or nil) and an error string. Those
@@ -351,8 +359,8 @@ function bind(addr, port)
-- NSE-specific errors:
-- * "Sorry, you don't have OpenSSL": The protocol is "ssl" but Nmap was compiled without OpenSSL support.
-- * "invalid connection method": The second parameter is not one of "tcp", "udp", and "ssl".
--- @param hostid Hostname or IP address.
--- @param port Port number.
+-- @param host Host table, hostname or IP address.
+-- @param port Port table or number.
-- @param protocol "tcp", "udp", or
-- "ssl" (default "tcp").
-- @return Status (true or false).
@@ -363,7 +371,7 @@ function bind(addr, port)
-- if not status then
-- return string.format("Can't connect: %s", err)
-- end
-function connect(hostid, port, protocol)
+function connect(host, port, protocol)
--- Reconnect the open (connected) socket with SSL.
--