mirror of
https://github.com/nmap/nmap.git
synced 2025-12-07 13:11:28 +00:00
Support fragmented TLS records. Closes #194
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
# Nmap Changelog ($Id$); -*-text-*-
|
||||
|
||||
o [NSE] [GH#194] Add support for reading fragmented TLS messages to
|
||||
ssl-enum-ciphers. [Jacob Gajek]
|
||||
|
||||
o [Ncat] [GH#193] Fix Ncat listen mode over Unix sockets (named pipes) on OS X.
|
||||
This was crashing with the error:
|
||||
Ncat: getnameinfo failed: Undefined error: 0 QUITTING.
|
||||
|
||||
@@ -1110,10 +1110,12 @@ end
|
||||
-- Read a SSL/TLS record
|
||||
-- @param buffer The read buffer
|
||||
-- @param i The position in the buffer to start reading
|
||||
-- @param fragment Message fragment left over from previous record (nil if none)
|
||||
-- @return The current position in the buffer
|
||||
-- @return The record that was read, as a table
|
||||
function record_read(buffer, i)
|
||||
function record_read(buffer, i, fragment)
|
||||
local b, h, len
|
||||
local add = 0
|
||||
|
||||
------------
|
||||
-- Header --
|
||||
@@ -1148,6 +1150,14 @@ function record_read(buffer, i)
|
||||
return i, nil
|
||||
end
|
||||
|
||||
-- Adjust buffer and length to account for message fragment left over
|
||||
-- from last record.
|
||||
if fragment then
|
||||
add = #fragment
|
||||
len = len + add
|
||||
buffer = buffer:sub(1, j - 1) .. fragment .. buffer:sub(j, -1)
|
||||
end
|
||||
|
||||
-- Convert to human-readable form.
|
||||
|
||||
----------
|
||||
@@ -1155,12 +1165,11 @@ function record_read(buffer, i)
|
||||
----------
|
||||
|
||||
h["body"] = {}
|
||||
while j < len do
|
||||
|
||||
while j <= len do
|
||||
-- RFC 2246, 6.2.1 "multiple client messages of the same ContentType may
|
||||
-- be coalesced into a single TLSPlaintext record"
|
||||
-- TODO: implement reading of fragmented records
|
||||
b = {}
|
||||
table.insert(h["body"], b)
|
||||
if h["type"] == "alert" then
|
||||
-- Parse body.
|
||||
j, b["level"] = bin.unpack("C", buffer, j)
|
||||
@@ -1169,7 +1178,16 @@ function record_read(buffer, i)
|
||||
-- Convert to human-readable form.
|
||||
b["level"] = find_key(TLS_ALERT_LEVELS, b["level"])
|
||||
b["description"] = find_key(TLS_ALERT_REGISTRY, b["description"])
|
||||
|
||||
table.insert(h["body"], b)
|
||||
elseif h["type"] == "handshake" then
|
||||
|
||||
-- Check for message fragmentation.
|
||||
if len - j < 3 then
|
||||
h.fragment = buffer:sub(j, len)
|
||||
return len + 1 - add, h
|
||||
end
|
||||
|
||||
-- Parse body.
|
||||
j, b["type"] = bin.unpack("C", buffer, j)
|
||||
local msg_end
|
||||
@@ -1179,6 +1197,12 @@ function record_read(buffer, i)
|
||||
-- Convert to human-readable form.
|
||||
b["type"] = find_key(TLS_HANDSHAKETYPE_REGISTRY, b["type"])
|
||||
|
||||
-- Check for message fragmentation.
|
||||
if msg_end > len + 1 then
|
||||
h.fragment = buffer:sub(j - 4, len)
|
||||
return len + 1 - add, h
|
||||
end
|
||||
|
||||
if b["type"] == "server_hello" then
|
||||
-- Parse body.
|
||||
j, b["protocol"] = bin.unpack(">S", buffer, j)
|
||||
@@ -1226,9 +1250,12 @@ function record_read(buffer, i)
|
||||
stdnse.debug2("Unknown handshake message type: %s", b["type"])
|
||||
j, b["data"] = bin.unpack("A" .. msg_end - j, buffer, j)
|
||||
end
|
||||
|
||||
table.insert(h["body"], b)
|
||||
elseif h["type"] == "heartbeat" then
|
||||
j, b["type"], b["payload_length"] = bin.unpack("C>S", buffer, j)
|
||||
j, b["payload"], b["padding"] = bin.unpack("PP", buffer, j)
|
||||
table.insert(h["body"], b)
|
||||
else
|
||||
stdnse.debug1("Unknown message type: %s", h["type"])
|
||||
end
|
||||
@@ -1237,7 +1264,7 @@ function record_read(buffer, i)
|
||||
-- Ignore unparsed bytes.
|
||||
j = len + 1
|
||||
|
||||
return j, h
|
||||
return j - add, h
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
@@ -149,20 +149,22 @@ end
|
||||
local function get_record_iter(sock)
|
||||
local buffer = ""
|
||||
local i = 1
|
||||
local fragment
|
||||
return function ()
|
||||
local record
|
||||
i, record = tls.record_read(buffer, i)
|
||||
i, record = tls.record_read(buffer, i, fragment)
|
||||
if record == nil then
|
||||
local status, err
|
||||
status, buffer, err = tls.record_buffer(sock, buffer, i)
|
||||
if not status then
|
||||
return nil, err
|
||||
end
|
||||
i, record = tls.record_read(buffer, i)
|
||||
i, record = tls.record_read(buffer, i, fragment)
|
||||
if record == nil then
|
||||
return nil, "done"
|
||||
end
|
||||
end
|
||||
fragment = record.fragment
|
||||
return record
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user