mirror of
https://github.com/nmap/nmap.git
synced 2025-12-06 04:31:29 +00:00
Change the lookup for specialized negotiation functions in ssl-cert.nse.
Instead of having an array called STARTTLS_PORTS, with linear lookup for membership, defined SPECIALIZED_FUNCS, mapping port numbers to negotiation functions. This make sit a little easier to add other SSL negotiation mechanisms, like HTTP Upgrade.
This commit is contained in:
@@ -74,17 +74,86 @@ local date_to_string
|
|||||||
local table_find
|
local table_find
|
||||||
local s
|
local s
|
||||||
|
|
||||||
local STARTTLS_PORTS = { 25, 587 }
|
function smtp_starttls(host, port)
|
||||||
|
-- Attempt to negotiate TLS over SMTP for services that support it
|
||||||
|
-- Works for SMTP (25) and SMTP Submission (587)
|
||||||
|
|
||||||
|
-- Open a standard TCP socket
|
||||||
|
local status, error = s:connect(host, port, "tcp")
|
||||||
|
|
||||||
|
if not status then
|
||||||
|
return nil
|
||||||
|
else
|
||||||
|
|
||||||
|
-- Loop until the service presents a banner to deal with server
|
||||||
|
-- load and timing issues. There may be a better way to handle this.
|
||||||
|
local i = 0
|
||||||
|
repeat
|
||||||
|
status, resultEHLO = s:receive_lines(1)
|
||||||
|
i = i + 1
|
||||||
|
until string.match(resultEHLO, "^220") or i == 5
|
||||||
|
|
||||||
|
-- Send EHLO because the the server expects it
|
||||||
|
-- We are not going to check for STARTTLS in the capabilities
|
||||||
|
-- list, sometimes it is not advertised.
|
||||||
|
local query = "EHLO example.org\r\n"
|
||||||
|
status = s:send(query)
|
||||||
|
status, resultEHLO = s:receive_lines(1)
|
||||||
|
|
||||||
|
if not (string.match(resultEHLO, "^250")) then
|
||||||
|
stdnse.print_debug("1","%s",resultEHLO)
|
||||||
|
stdnse.print_debug("1","EHLO with errors or timeout. Enable --script-trace to see what is happening.")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
resultEHLO = ""
|
||||||
|
|
||||||
|
-- Send STARTTLS command ask the service to start encryption
|
||||||
|
local query = "STARTTLS\r\n"
|
||||||
|
status = s:send(query)
|
||||||
|
status, resultEHLO = s:receive_lines(1)
|
||||||
|
|
||||||
|
if not (string.match(resultEHLO, "^220")) then
|
||||||
|
stdnse.print_debug("1","%s",resultEHLO)
|
||||||
|
stdnse.print_debug("1","STARTTLS failed or unavailable. Enable --script-trace to see what is happening.")
|
||||||
|
|
||||||
|
-- Send QUIT to clean up server side connection
|
||||||
|
local query = "QUIT\r\n"
|
||||||
|
status = s:send(query)
|
||||||
|
resultEHLO = ""
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Service supports STARTTLS, tell NSE start SSL negotiation
|
||||||
|
status, error = s:reconnect_ssl()
|
||||||
|
if not status then
|
||||||
|
stdnse.print_debug("1","Could not establish SSL session after STARTTLS command.")
|
||||||
|
s:close()
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
-- Should have a solid TLS over SMTP session now...
|
||||||
|
return "Connected"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- A table mapping port numbers to specialized SSL negotiation functions.
|
||||||
|
local SPECIALIZED_FUNCS = { [25] = smtp_starttls, [587] = smtp_starttls }
|
||||||
|
|
||||||
portrule = function(host, port)
|
portrule = function(host, port)
|
||||||
return shortport.ssl(host, port) or table_find(STARTTLS_PORTS, port.number)
|
return shortport.ssl(host, port) or SPECIALIZED_FUNCS[port.number]
|
||||||
end
|
end
|
||||||
|
|
||||||
action = function(host, port)
|
action = function(host, port)
|
||||||
|
local specialized
|
||||||
|
|
||||||
s = nmap.new_socket()
|
s = nmap.new_socket()
|
||||||
|
|
||||||
if table_find(STARTTLS_PORTS, port.number) then
|
-- Is there a specialized function for this port?
|
||||||
local status = starttls_negotiate(host,port)
|
specialized = SPECIALIZED_FUNCS[port.number]
|
||||||
|
if specialized then
|
||||||
|
local status = specialized(host, port)
|
||||||
|
|
||||||
if not status then
|
if not status then
|
||||||
return nil
|
return nil
|
||||||
@@ -186,67 +255,3 @@ function date_to_string(date)
|
|||||||
return os.date("%Y-%m-%d %H:%M:%S", os.time(date))
|
return os.date("%Y-%m-%d %H:%M:%S", os.time(date))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function starttls_negotiate(host, port)
|
|
||||||
-- Attempt to negotiate TLS over SMTP for services that support it
|
|
||||||
-- Works for SMTP (25) and SMTP Submission (587)
|
|
||||||
|
|
||||||
-- Open a standard TCP socket
|
|
||||||
local status, error = s:connect(host, port, "tcp")
|
|
||||||
|
|
||||||
if not status then
|
|
||||||
return nil
|
|
||||||
else
|
|
||||||
|
|
||||||
-- Loop until the service presents a banner to deal with server
|
|
||||||
-- load and timing issues. There may be a better way to handle this.
|
|
||||||
local i = 0
|
|
||||||
repeat
|
|
||||||
status, resultEHLO = s:receive_lines(1)
|
|
||||||
i = i + 1
|
|
||||||
until string.match(resultEHLO, "^220") or i == 5
|
|
||||||
|
|
||||||
-- Send EHLO because the the server expects it
|
|
||||||
-- We are not going to check for STARTTLS in the capabilities
|
|
||||||
-- list, sometimes it is not advertised.
|
|
||||||
local query = "EHLO example.org\r\n"
|
|
||||||
status = s:send(query)
|
|
||||||
status, resultEHLO = s:receive_lines(1)
|
|
||||||
|
|
||||||
if not (string.match(resultEHLO, "^250")) then
|
|
||||||
stdnse.print_debug("1","%s",resultEHLO)
|
|
||||||
stdnse.print_debug("1","EHLO with errors or timeout. Enable --script-trace to see what is happening.")
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
resultEHLO = ""
|
|
||||||
|
|
||||||
-- Send STARTTLS command ask the service to start encryption
|
|
||||||
local query = "STARTTLS\r\n"
|
|
||||||
status = s:send(query)
|
|
||||||
status, resultEHLO = s:receive_lines(1)
|
|
||||||
|
|
||||||
if not (string.match(resultEHLO, "^220")) then
|
|
||||||
stdnse.print_debug("1","%s",resultEHLO)
|
|
||||||
stdnse.print_debug("1","STARTTLS failed or unavailable. Enable --script-trace to see what is happening.")
|
|
||||||
|
|
||||||
-- Send QUIT to clean up server side connection
|
|
||||||
local query = "QUIT\r\n"
|
|
||||||
status = s:send(query)
|
|
||||||
resultEHLO = ""
|
|
||||||
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Service supports STARTTLS, tell NSE start SSL negotiation
|
|
||||||
status, error = s:reconnect_ssl()
|
|
||||||
if not status then
|
|
||||||
stdnse.print_debug("1","Could not establish SSL session after STARTTLS command.")
|
|
||||||
s:close()
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
-- Should have a solid TLS over SMTP session now...
|
|
||||||
return "Connected"
|
|
||||||
end
|
|
||||||
|
|||||||
Reference in New Issue
Block a user