local nmap = require "nmap"
local stdnse = require "stdnse"
local shortport = require "shortport"
local table = require "table"
local ike = require "ike"


description=[[
	Get information from an IKE service.
	Tests the service with both Main and Aggressive Mode. 
	Extracts ID info (if aggressive mode is enabled), and 
	vendor IDs
]]


---
-- @output
-- PORT    STATE SERVICE REASON       VERSION
-- 500/udp open  isakmp  udp-response SonicWall
-- | ike-info: 
-- | Information
-- |   ID details
-- |     Type
-- |       ID_USER_FQDN
-- |     Value
-- |       DJ-G005
-- |   Vendor IDs
-- |_    SonicWall 


author = "Jesper Kueckelhahn"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"discovery", "safe"}

portrule = shortport.port_or_service(500, "isakmp", "udp")


-- Test different methods for getting version 
-- 
local function get_version(host, port)
	local packet, version, t 
	local auth			= {"psk", "rsa", "Hybrid", "XAUTH"}
	local encryption	= {"des", "3des", "aes/128", "aes/192", "aes/256"}
	local hash			= {"md5", "sha1"}
	local group			= {"768", "1024", "1536"}


	-- generate transforms
	t = {}
	for h,a in pairs(auth) do
		for i,e in pairs(encryption) do
			for j,h in pairs(hash) do
				for k,g in pairs(group) do
					table.insert(t, { ['auth'] = a, ['encryption'] = e, ['hash'] = h, ['group'] = g});
				end
			end
		end
	end

	-- try aggressive mode (diffie hellman group 2)
	local diffie = 2
	stdnse.print_debug(1, "Sending Aggressive mode packet ...")
	packet = ike.request(port.number, port.protocol, 'Aggressive', t, diffie, 'vpngroup')
	version = ike.send_request(host, port, packet)
	if version.success then
		return version
	end
	stdnse.print_debug(1, "Aggressive mode (dh 2) failed")

	-- try aggressive mode (diffie hellman group 1)
	diffie = 1
	stdnse.print_debug(1, "Sending Aggressive mode packet ...")
	packet = ike.request(port.number, port.protocol, 'Aggressive', t, diffie, 'vpngroup')
	version = ike.send_request(host, port, packet)
	if version.success then
		return version
	end
	stdnse.print_debug(1, "Aggressive mode (dh 1) failed")

	-- try aggressive mode (diffie hellman group 2, no id)
	-- some checkpoint devices respond to this
	local diffie = 2
	stdnse.print_debug(1, "Sending Aggressive mode packet ...")
	packet = ike.request(port.number, port.protocol, 'Aggressive', t, diffie, '')
	version = ike.send_request(host, port, packet)
	if version.success then
		return version
	end
	stdnse.print_debug(1, "Aggressive mode (dh 2, no id) failed")

	-- try main mode
	stdnse.print_debug(1, "Sending Main mode packet ...")
	packet = ike.request(port.number, port.protocol, 'Main', t, '')
	version = ike.send_request(host, port, packet)
	if version.success then
		return version
	end
	stdnse.print_debug(1, "Main mode failed")

	return false
end


action = function( host, port )
	local ike_response = get_version(host, port)
	local results = {['name'] = "Information"}

	if ike_response then
		
		-- extract ID
		if ike_response['response']['ID'] ~= nil then
			local id = { ['name'] = "ID details" }			
			for _, id_payload in pairs(ike_response['response']['ID']) do			
				local t = ike.parse_id_type(id_payload)
				table.insert(id, {['name']='Type', t['type']})
				table.insert(id, {['name']='Value', t['value']})
			end
			table.insert(results, id)
		end

		-- extract vendor IDs
		if ike_response['info'] ~= nil then
			local vids = { ['name'] = "Vendor IDs" }			
			for _,vid in ipairs(ike_response['info']['matches']) do			
				table.insert(vids, vid['match'])
			end
			table.insert(results, vids)
		end
	end

	return stdnse.format_output(true, results)
end



