diff --git a/nselib/imap.lua b/nselib/imap.lua new file mode 100644 index 000000000..e280cba07 --- /dev/null +++ b/nselib/imap.lua @@ -0,0 +1,45 @@ +--- IMAP functions. +-- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html + +module(... or "imap", package.seeall) + +require 'stdnse' + + +--- +-- Asks an IMAP server for capabilities. +-- +-- See RFC 3501. +-- @param host Host to be queried. +-- @param port Port to connect to. +-- @return Table containing capabilities or nil on error. +-- @return nil or String error message. +function capabilities(host, port) + local socket = nmap.new_socket() + local capas = {} + socket:set_timeout(10000) + local proto = (port.version and port.version.service_tunnel == "ssl" and "ssl") or "tcp" + if not socket:connect(host.ip, port.number, proto) then return nil, "Could Not Connect" end + + status, line = socket:receive_lines(1) + if not string.match(line, "^[%*] OK") then return nil, "No Response" end + + socket:send("a001 CAPABILITY\r\n") + status, line = socket:receive_buf("\r\n", false) + if not status then + capas.CAPABILITY = false + else + while status do + if string.match(line, "^%*%s+CAPABILITY") then + line = string.gsub(line, "^%*%s+CAPABILITY", "") + for capability in string.gmatch(line, "[%w%+=-]+") do + capas[capability] = true + end + break + end + status, line = socket:receive_buf("\r\n", false) + end + end + socket:close() + return capas +end diff --git a/scripts/imap-capabilities.nse b/scripts/imap-capabilities.nse new file mode 100644 index 000000000..51ee600fb --- /dev/null +++ b/scripts/imap-capabilities.nse @@ -0,0 +1,42 @@ +description = [[ +Retrieves IMAP email server capabilities. + +IMAP4rev1 capabilities are defined in RFC 3501. The CAPABILITY command +allows a client to ask a server what commands it supports and possibly +any site-specific policy. +]] + +--- +-- @output +-- 143/tcp open imap +-- |_ imap-capabilities: LOGINDISABLED IDLE IMAP4 LITERAL+ STARTTLS NAMESPACE IMAP4rev1 + + +author = "Brandon Enright " +license = "Same as Nmap--See http://nmap.org/book/man-legal.html" + +categories = {"default"} + +require 'imap' +require 'shortport' +require 'stdnse' + +portrule = shortport.port_or_service({143}, "imap") + +action = function(host, port) + local capa, err = imap.capabilities(host, port) + if type(capa) == "table" then + -- Convert the capabilities table into an array of strings. + local capstrings = {} + local cap, args + for cap, args in pairs(capa) do + table.insert(capstrings, cap) + end + return stdnse.strjoin(" ", capstrings) + elseif type(err) == "string" then + stdnse.print_debug(1, "%s: '%s' for %s", filename, err, host.ip) + return + else + return "server doesn't support CAPABILITIES" + end +end diff --git a/scripts/script.db b/scripts/script.db index 08bdd56f6..c03e8f8c3 100644 --- a/scripts/script.db +++ b/scripts/script.db @@ -18,6 +18,7 @@ Entry { filename = "http-open-proxy.nse", categories = { "default", "discovery", Entry { filename = "http-passwd.nse", categories = { "intrusive", "vuln", } } Entry { filename = "http-trace.nse", categories = { "discovery", } } Entry { filename = "iax2-version.nse", categories = { "version", } } +Entry { filename = "imap-capabilities.nse", categories = { "default", } } Entry { filename = "irc-info.nse", categories = { "default", "discovery", } } Entry { filename = "ms-sql-info.nse", categories = { "default", "discovery", "intrusive", } } Entry { filename = "mysql-info.nse", categories = { "default", "discovery", "safe", } }