From 72af4637b092ae645f2736220921168ac66045ec Mon Sep 17 00:00:00 2001 From: patrik Date: Wed, 22 Feb 2012 20:03:15 +0000 Subject: [PATCH] o [NSE] Added host based registry, which allows scripts to share data between scripts scanning a specific host. [Patrik] --- CHANGELOG | 3 +++ docs/scripting.xml | 62 +++++++++++++++++++++++++++------------------- nse_main.lua | 15 ++++++++--- nse_nmaplib.cc | 3 +++ 4 files changed, 54 insertions(+), 29 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index af7880d4a..0a69b64e8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,8 @@ # Nmap Changelog ($Id$); -*-text-*- +o [NSE] Added host based registry, which allows scripts to share data between + scripts scanning a specific host. [Patrik] + o [NSE] Applied patch from Andrew Orr that fixes the recent changes in the BitCoin protocol. [Patrik] diff --git a/docs/scripting.xml b/docs/scripting.xml index bc2e1bbb1..a7c45a3c1 100644 --- a/docs/scripting.xml +++ b/docs/scripting.xml @@ -2147,34 +2147,46 @@ try(socket:send(result)) The Registry registry (NSE) - - The registry is a Lua table (accessible - as nmap.registry) with the special property - that it is visible by all scripts and retains its state - between script executions. The registry is transient—it - is not stored between Nmap executions. Every script can read - and write to the registry. Scripts commonly use it to save - information for other instances of the same script. For - example, the whois - and asn-query scripts may query one IP - address, but receive information which may apply to tens of - thousands of IPs on that network. Saving the information in - the registry may prevent other script threads from having to - repeat the query. + Scripts can share information by stroring values in a + register, which is a special table that can be + accessed by all scripts. There is a global registry with the name + nmap.registry, shared by all scripts. Each host + additionally has its own registry called + host.registry, where host is the + host table passed to a script. + Information in the registries is not stored between Nmap + executions. - The registry may also be used to hand - information to completely different scripts. For example, - the snmp-brute script saves a discovered - community name in the registry where it may be used by other - SNMP scripts. Script which use the results of another script - must declare it using the dependencies - variable to make sure that the earlier script runs first. - + The global registry persists throughout an entire scan session. + Scripts can use it, for example, to store values that will later be + displayed by a postrule script. The per-host registries, on the other + hand, only exist while a host is being scanned. They can be used to send + information from one script to another one that runs against the same + host. When possible, use the per-host registry; this not only saves you + from having to make key names unique across hosts, but also allows the + memory used by the registry to be reclaimed when it is no longer + needed. - Because every script can write to the registry table, it - is important to avoid conflicts by choosing keys wisely - (uniquely). + + Here are examples of using both registries: + + The portrule of the ssh-hostkey script collects SSH key fingerprints + and stores them in the global nmap.registry so they + can be printed later by the postrule. + The ssl-cert script collects SSL certificates and + stores them in the per-host registry so that the + ssl-google-cert-catalog script can use them without + having to make another connection to the server. + + + Because every script can write to the global registry table, it is + important to make the keys you use unique, to avoid overwriting the keys + of other scripts (or the same script running in parallel). + + Scripts that use the results of another script must declare it using + the dependencies variable to make sure that the earlier + script runs first. diff --git a/nse_main.lua b/nse_main.lua index b4b923f82..595e8db24 100644 --- a/nse_main.lua +++ b/nse_main.lua @@ -219,6 +219,13 @@ local function tcopy (t) return tc; end +-- copies the host table while preserving the registry +local function host_copy(t) + local h = tcopy(t) + h.registry = t.registry + return h +end + local REQUIRE_ERROR = {}; rawset(stdnse, "silent_require", function (...) local status, mod = pcall(require, ...); @@ -1179,18 +1186,18 @@ local function main (hosts, scantype) -- Check hostrules for this host. for j, host in ipairs(hosts) do for _, script in ipairs(scripts) do - local thread = script:new_thread("hostrule", tcopy(host)); + local thread = script:new_thread("hostrule", host_copy(host)); if thread then - thread.args, thread.host = {n = 1, tcopy(host)}, host; + thread.args, thread.host = {n = 1, host_copy(host)}, host; yield(thread); end end -- Check portrules for this host. for port in cnse.ports(host) do for _, script in ipairs(scripts) do - local thread = script:new_thread("portrule", tcopy(host), tcopy(port)); + local thread = script:new_thread("portrule", host_copy(host), tcopy(port)); if thread then - thread.args, thread.host, thread.port = {n = 2, tcopy(host), tcopy(port)}, host, port; + thread.args, thread.host, thread.port = {n = 2, host_copy(host), tcopy(port)}, host, port; yield(thread); end end diff --git a/nse_nmaplib.cc b/nse_nmaplib.cc index 11b671f00..f09483821 100644 --- a/nse_nmaplib.cc +++ b/nse_nmaplib.cc @@ -154,6 +154,9 @@ void set_hostinfo(lua_State *L, Target *currenths) { setnfield(L, -1, "timeout", (lua_Number) currenths->to.timeout / 1000000.0); lua_setfield(L, -2, "times"); + lua_newtable(L); + lua_setfield(L, -2, "registry"); + /* add distance (in hops) if traceroute has been performed */ if (currenths->traceroute_hops.size() > 0) {