summaryrefslogtreecommitdiffstats
path: root/scripts/dict-info.nse
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/dict-info.nse')
-rw-r--r--scripts/dict-info.nse79
1 files changed, 79 insertions, 0 deletions
diff --git a/scripts/dict-info.nse b/scripts/dict-info.nse
new file mode 100644
index 0000000..73aaabe
--- /dev/null
+++ b/scripts/dict-info.nse
@@ -0,0 +1,79 @@
+local nmap = require "nmap"
+local match = require "match"
+local shortport = require "shortport"
+local stdnse = require "stdnse"
+local table = require "table"
+
+description = [[
+Connects to a dictionary server using the DICT protocol, runs the SHOW
+SERVER command, and displays the result. The DICT protocol is defined in RFC
+2229 and is a protocol which allows a client to query a dictionary server for
+definitions from a set of natural language dictionary databases.
+
+The SHOW server command must be implemented and depending on access will show
+server information and accessible databases. If authentication is required, the
+list of databases will not be shown.
+]]
+
+---
+-- @usage
+-- nmap -p 2628 <ip> --script dict-info
+--
+-- @output
+-- PORT STATE SERVICE
+-- 2628/tcp open dict
+-- | dict-info:
+-- | dictd 1.12.0/rf on Linux 3.0.0-12-generic
+-- | On ubu1110: up 15.000, 4 forks (960.0/hour)
+-- |
+-- | Database Headwords Index Data Uncompressed
+-- | bouvier 6797 128 kB 2338 kB 6185 kB
+-- |_ fd-eng-swe 5489 76 kB 77 kB 204 kB
+--
+
+author = "Patrik Karlsson"
+license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
+categories = {"discovery", "safe"}
+
+
+portrule = shortport.port_or_service(2628, "dict", "tcp")
+
+local function fail(err) return stdnse.format_output(false, err) end
+
+action = function(host, port)
+ local socket = nmap.new_socket()
+ if ( not(socket:connect(host, port)) ) then
+ return fail("Failed to connect to dictd server")
+ end
+
+ local probes = {
+ 'client "dict 1.12.0/rf on Linux 3.0.0-12-generic"',
+ 'show server',
+ 'quit',
+ }
+
+ if ( not(socket:send(table.concat(probes, "\r\n") .. "\r\n")) ) then
+ return fail("Failed to send request to server")
+ end
+
+ local srvinfo
+
+ repeat
+ local status, data = socket:receive_buf(match.pattern_limit("\r\n", 2048), false)
+ if ( not(status) ) then
+ return fail("Failed to read response from server")
+ elseif ( data:match("^5") ) then
+ return fail(data)
+ elseif ( data:match("^114") ) then
+ srvinfo = {}
+ elseif ( srvinfo and not(data:match("^%.$")) ) then
+ table.insert(srvinfo, data)
+ end
+ until(not(status) or data:match("^221") or data:match("^%.$"))
+ socket:close()
+
+ -- if last item is an empty string remove it, to avoid trailing line feed
+ srvinfo[#srvinfo] = ( srvinfo[#srvinfo] ~= "" and srvinfo[#srvinfo] or nil )
+
+ return stdnse.format_output(true, srvinfo)
+end