Index: nselib/ike.lua
===================================================================
--- nselib/ike.lua	(revision 30907)
+++ nselib/ike.lua	(working copy)
@@ -36,32 +36,69 @@
 license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
 categories = {"discovery", "safe"}
 
-local enc_methods	= { 
+ENC_METHODS	= { 
 	["des"]    = 0x80010001, 
 	["3des"]   = 0x80010005, 
+	["cast"]   = 0x80010006, 
 	["aes/128"]= { 0x80010007, 0x800E0080 }, 
 	["aes/192"]= { 0x80010007, 0x800E00C0 }, 
 	["aes/256"]= { 0x80010007, 0x800E0100 } 
 }
 
+AUTH_TYPES = { 
+	["psk"]    = 0x80030001, 
+	["rsa"]    = 0x80030003, 
+	["ECDSA"]  = 0x80030008,
+	["Hybrid"] = 0x8003FADD, 
+	["XAUTH"]  = 0x8003FDE9,
+}
 
-local authentication= { ["psk"] = 0x80030001, ["rsa"] = 0x80030003, ["Hybrid"] = 0x8003FADD, ["XAUTH"] = 0x8003FDE9}
+GROUP_DESCRIPTION = { 
+	["768"]  = 0x80040001, 
+	["1024"] = 0x80040002, 
+	["1536"] = 0x80040005,
+	["2048"] = 0x0004000E
+}
 
-local hash_algo		= { ["md5"] = 0x80020001, ["sha1"] = 0x80020002}
-local group_desc	= { ["768"] = 0x80040001, ["1024"] = 0x80040002, ["1536"]= 0x80040005}
-local exchange_mode = { ["Main"] = 0x02, ["Aggressive"]= 0x04}
-local protocol_ids	= { ["tcp"]  = "06", ["udp"]= "11"}
+EXCHANGE_MODE = { 
+	["Main"]       = 0x02, 
+	["Aggressive"] = 0x04
+}
 
+HASH_ALGORITHM = { 
+	["md5"]      = 0x80020001,
+	["sha1"]     = 0x80020002,
+	["sha2-256"] = 0x80020004,
+	["sha2-384"] = 0x80020005,
+	["sha2-512"] = 0x80020006,
+}
 
--- Response packet types
-local response_exchange_type = {
+PROTOCOL_IDS = { 
+	["tcp"] = "06", 
+	["udp"] = "11"
+}
+
+EXCHANGE_TYPE = {
 	["02"] = "Main",
 	["04"] = "Aggressive",
 	["05"] = "Informational"
 }
 
--- Payload names
-local payloads = {
+ID_TYPES = {
+	["01"] = "ID_IPV4_ADDR",
+	["02"] = "ID_FQDN",
+	["03"] = "ID_USER_FQDN",
+	["04"] = "ID_IPV4_ADDR_SUBNET",
+	["05"] = "ID_IPV6_ADDR",
+	["06"] = "ID_IPV6_ADDR_SUBNET",
+	["07"] = "ID_IPV4_ADDR_RANGE",
+	["08"] = "ID_IPV6_ADDR_RANGE",
+	["09"] = "ID_DER_ASN1_DN",
+	["0A"] = "ID_DER_ASN1_GN",
+	["0B"] = "ID_KEY_ID"
+}
+
+PAYLOADS = {
 	["00"] = "None",
 	["01"] = "SA",
 	["03"] = "Transform",
@@ -125,7 +162,6 @@
 --
 local function convert_to_hex(id)
 	local hex_str = ""
-
 	for c in string.gmatch(id, ".") do 
 		hex_str = hex_str .. string.format("%X", c:byte()) 
 	end
@@ -133,6 +169,44 @@
 end
 
 
+-- convert a hex string to ascii
+--
+local function convert_to_str(hex_str)
+	local str = ""
+	for c in string.gmatch(hex_str, "..") do 
+		str = str .. string.char("0x" .. c)
+	end
+	return str
+end
+
+
+function parse_id_type(id_payload)
+	
+	-- get id type
+	local id_type = id_payload:sub(0, 2)
+
+	-- remove the rest of the payload headers
+	id_payload = id_payload:sub(9, #id_payload)
+
+	local is_ipv4 = (id_type == "01" or id_type == "04" or id_type == "07")
+	local is_string = (id_type == "02" or id_type == "03")
+
+	if is_ipv4 then
+		-- convert hex to readable IP address
+		local a = tonumber(id_payload:sub(1,2), 16)
+		local b = tonumber(id_payload:sub(3,4), 16)
+		local c = tonumber(id_payload:sub(5,6), 16)
+		local d = tonumber(id_payload:sub(7,8), 16)
+		return {['type'] = ID_TYPES[id_type], ['value'] = a .. '.' .. b .. '.' .. c .. '.' .. d }
+	elseif is_string then
+		return {["type"] = ID_TYPES[id_type], ["value"] = convert_to_str(id_payload) } 
+	else
+		return {["type"] = ID_TYPES[id_type], ["value"] = ''}
+	end
+end
+
+
+
 -- Extract Payloads
 local function extract_payloads(packet)
 	
@@ -145,22 +219,22 @@
 	local payload = ''
 
 	-- loop over packet
-	while payloads[np] ~= "None" and index <= packet:len() do
+	while PAYLOADS[np] ~= "None" and index <= packet:len() do
 		local payload_length = tonumber("0x"..packet:sub(index, index+3)) * 2
 		payload = string.lower(packet:sub(index+4, index+payload_length-5))
 
 		-- debug
-		if payloads[np] == 'VID' then
-			stdnse.print_debug(2, 'IKE: Found IKE Header: %s: %s - %s', np, payloads[np], payload)
+		if PAYLOADS[np] == 'VID' then
+			stdnse.print_debug(2, 'IKE: Found IKE Header: %s: %s - %s', np, PAYLOADS[np], payload)
 		else
-			stdnse.print_debug(2, 'IKE: Found IKE Header: %s: %s', np, payloads[np])
+			stdnse.print_debug(2, 'IKE: Found IKE Header: %s: %s', np, PAYLOADS[np])
 		end
 
 		-- Store payload
-		if ike_headers[payloads[np]] == nil then
-			ike_headers[payloads[np]] = {payload}
+		if ike_headers[PAYLOADS[np]] == nil then
+			ike_headers[PAYLOADS[np]] = {payload}
 		else
-			table.insert(ike_headers[payloads[np]], payload)
+			table.insert(ike_headers[PAYLOADS[np]], payload)
 		end
 
 		-- find the next payload type
@@ -197,6 +271,7 @@
 	local info = {
 		vendor = nil,
 		attribs = {},
+		matches = {}
 	}
 
 	local status, fingerprints
@@ -214,23 +289,22 @@
 
 					-- if a match is found, check if it's a version detection or attribute
 					if row.category == 'vendor' then
+						local debug_string = ''
+						if row.vendor  ~= nil then debug_string = debug_string .. row.vendor .. ' ' end
+						if row.version ~= nil then debug_string = debug_string .. row.version       end	
+						stdnse.print_debug(2, "IKE: Fingerprint: %s matches %s", vendor_id,  debug_string)
+						table.insert(info.matches, { ['vid'] = vendor_id, ['match'] = debug_string} )
 						
 						-- Only store the first match
 						if info.vendor == nil then
-
 							-- the fingerprint contains information about the VID
 							info.vendor = row
+						end
 
-							local debug_string = ''
-							if row.vendor  ~= nil then debug_string = debug_string .. row.vendor .. ' ' end
-							if row.version ~= nil then debug_string = debug_string .. row.version       end	
-
-							stdnse.print_debug(2, "IKE: Fingerprint: %s matches %s", vendor_id,  debug_string)
-						end
-					
 					elseif row.category == 'attribute' then
 						info.attribs[ #info.attribs + 1] = row
 						stdnse.print_debug(2, "IKE: Attribute: %s matches %s", vendor_id, row.text)
+						table.insert(info.matches, { ['vid'] = vendor_id, ['match'] = row.text} )
 						break
 					end
 				end
@@ -304,7 +378,7 @@
 	if packet:len() > 38 then
 
 		-- extract the return type
-		local resp_type = response_exchange_type[packet:sub(37,38)]
+		local resp_type = EXCHANGE_TYPE[packet:sub(37,38)]
 		local ike_headers = {}
 
 		-- simple check that the type is something other than 'Informational'
@@ -320,6 +394,9 @@
 			-- search for fingerprints
 			resp["info"]	= lookup(resp['vids'])
 
+			-- add the complete ike response
+			resp['response'] = ike_headers
+
 			-- indicate that a packet 'useful' packet was returned
 			resp['success'] = true
 		end
@@ -338,6 +415,10 @@
 	local socket = nmap.new_socket()
 	local s_status, r_status, data, i, hexstring, _
 
+	-- lock resource (port 500/udp)
+	local mutex = nmap.mutex("ike_port_500");
+	mutex "lock";
+
 	-- send the request packet
 	socket:set_timeout(1000)
 	socket:bind(nil, port.number)
@@ -351,6 +432,9 @@
 		if r_status then
 			i, hexstring = bin.unpack("H" .. data:len(), data)
 			socket:close()
+			
+			-- release mutex
+			mutex "done";
 			return response(hexstring)	
 		else
 			socket:close()
@@ -359,6 +443,9 @@
 		socket:close()
 	end
 
+	-- release mutex
+	mutex "done";
+
 	return {}
 end
 
@@ -368,7 +455,7 @@
 --
 local function generate_aggressive(port, protocol, id, diffie)
 	local hex_port = string.format("%.4X", port)
-	local hex_prot = protocol_ids[protocol]
+	local hex_prot = PROTOCOL_IDS[protocol]
 	local id_len = string.format("%.4X", 8 + id:len())
 
 	-- get length of key data based on diffie
@@ -377,9 +464,10 @@
 		key_length = 96
 	elseif diffie == 2 then
 		key_length = 128
+	elseif diffie == 5 then
+		key_length = 192
 	end 
 
-
 	return bin.pack(">SHHSSHSHCHHH",
 		-- Key Exchange
 		0x0a00								, -- Next payload (Nonce)
@@ -413,11 +501,11 @@
 	-- handle special case of aes
 	if encryption:sub(1,3) == "aes" then
 		trans_length = 0x0028
-		enc = enc_methods[encryption][1]
-		key_length	= enc_methods[encryption][2]
+		enc = ENC_METHODS[encryption][1]
+		key_length	= ENC_METHODS[encryption][2]
 	else
 		trans_length = 0x0024
-		enc = enc_methods[encryption]
+		enc = ENC_METHODS[encryption]
 		key_length = nil
 	end
 
@@ -438,9 +526,9 @@
 		0x01				, -- Transform ID (IKE)
 		0x0000				, -- spacers ?
 		enc					, -- Encryption algorithm
-		hash_algo[hash]		, -- Hash algorithm
-		authentication[auth], -- Authentication method
-		group_desc[group]	 -- Group Description
+		HASH_ALGORITHM[hash], -- Hash algorithm
+		AUTH_TYPES[auth]    ,-- Authentication method
+		GROUP_DESCRIPTION[group]	 -- Group Description
 	)
 	
 	if key_length ~= nil then
@@ -502,7 +590,7 @@
 		0x0000000000000000	, -- Responder cookie
 		0x01				, -- Next payload (SA)
 		0x10				, -- Version
-		exchange_mode[mode]	, -- Exchange type
+		EXCHANGE_MODE[mode]	, -- Exchange type
 		0x00				, -- Flags
 		0x00000000			, -- Message id
 		l					, -- packet length
