mirror of
https://github.com/nmap/nmap.git
synced 2025-12-09 14:11:29 +00:00
Remove more bin.lua packings.
This commit is contained in:
106
nselib/coap.lua
106
nselib/coap.lua
@@ -1,4 +1,3 @@
|
|||||||
local bin = require "bin"
|
|
||||||
local comm = require "comm"
|
local comm = require "comm"
|
||||||
local json = require "json"
|
local json = require "json"
|
||||||
local lpeg = require "lpeg"
|
local lpeg = require "lpeg"
|
||||||
@@ -329,22 +328,23 @@ COAP.header.build = function(options)
|
|||||||
code = COAP.header.codes.build(code)
|
code = COAP.header.codes.build(code)
|
||||||
|
|
||||||
-- Build the fixed portion of the header.
|
-- Build the fixed portion of the header.
|
||||||
local pkt = ""
|
|
||||||
|
|
||||||
ver = ver << 6
|
ver = ver << 6
|
||||||
mtype = mtype << 4
|
mtype = mtype << 4
|
||||||
|
|
||||||
pkt = pkt .. bin.pack("C", ver | mtype | tkl)
|
local pkt = {
|
||||||
pkt = pkt .. code
|
string.pack("B", ver | mtype | tkl),
|
||||||
pkt = pkt .. bin.pack(">S", id)
|
code,
|
||||||
pkt = pkt .. token
|
string.pack(">I2", id),
|
||||||
|
token,
|
||||||
|
}
|
||||||
|
|
||||||
-- Include optional portions of the header.
|
-- Include optional portions of the header.
|
||||||
if options["options"] then
|
if options["options"] then
|
||||||
pkt = pkt .. COAP.header.options.build(options.options)
|
pkt[#pkt+1] = COAP.header.options.build(options.options)
|
||||||
end
|
end
|
||||||
|
|
||||||
return pkt
|
return table.concat(pkt)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Parses a CoAP message header.
|
--- Parses a CoAP message header.
|
||||||
@@ -361,9 +361,6 @@ end
|
|||||||
-- string containing the error message on failure.
|
-- string containing the error message on failure.
|
||||||
COAP.header.parse = function(buf, pos)
|
COAP.header.parse = function(buf, pos)
|
||||||
assert(type(buf) == "string")
|
assert(type(buf) == "string")
|
||||||
if #buf < 4 then
|
|
||||||
return false, "Cannot parse a string of less than four bytes."
|
|
||||||
end
|
|
||||||
|
|
||||||
if not pos or pos == 0 then
|
if not pos or pos == 0 then
|
||||||
pos = 1
|
pos = 1
|
||||||
@@ -371,14 +368,11 @@ COAP.header.parse = function(buf, pos)
|
|||||||
assert(type(pos) == "number")
|
assert(type(pos) == "number")
|
||||||
assert(pos <= #buf)
|
assert(pos <= #buf)
|
||||||
|
|
||||||
if pos + 4 - 1 > #buf then
|
if #buf - pos + 1 < 4 then
|
||||||
return false, "Fixed header extends past end of buffer."
|
return false, "Fixed header extends past end of buffer."
|
||||||
end
|
end
|
||||||
|
|
||||||
local pos, ver_type_tkl, code, id = bin.unpack("CA>S", buf, pos)
|
local ver_type_tkl, code, id, pos = string.unpack(">Bc1I2", buf, pos)
|
||||||
if not pos then
|
|
||||||
return false, "Failed to parse fixed header."
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Parse the fixed header.
|
-- Parse the fixed header.
|
||||||
local hdr = {}
|
local hdr = {}
|
||||||
@@ -486,7 +480,7 @@ COAP.header.codes.build = function(name)
|
|||||||
|
|
||||||
class = class << 5
|
class = class << 5
|
||||||
|
|
||||||
return bin.pack("C", class | detail)
|
return string.pack("B", class | detail)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Parses a CoAP request or response code.
|
--- Parses a CoAP request or response code.
|
||||||
@@ -511,7 +505,7 @@ COAP.header.codes.parse = function(buf, pos)
|
|||||||
assert(type(pos) == "number")
|
assert(type(pos) == "number")
|
||||||
assert(pos <= #buf)
|
assert(pos <= #buf)
|
||||||
|
|
||||||
local pos, id = bin.unpack("C", buf, pos)
|
local id, pos = string.unpack("B", buf, pos)
|
||||||
if not pos then
|
if not pos then
|
||||||
return false, id
|
return false, id
|
||||||
end
|
end
|
||||||
@@ -1462,20 +1456,8 @@ COAP.header.options.value.uint.build = function(val)
|
|||||||
if val == 0 then
|
if val == 0 then
|
||||||
return ""
|
return ""
|
||||||
end
|
end
|
||||||
|
-- strip leading null bytes to use smallest space
|
||||||
if val <= 255 then
|
return string.pack(">I16", val):gsub("^\0*","")
|
||||||
return bin.pack("C", val)
|
|
||||||
end
|
|
||||||
|
|
||||||
if val <= 65535 then
|
|
||||||
return bin.pack(">S", val)
|
|
||||||
end
|
|
||||||
|
|
||||||
if val <= 16777215 then
|
|
||||||
return bin.pack(">I", val):sub(2, 5)
|
|
||||||
end
|
|
||||||
|
|
||||||
return bin.pack(">I", val)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Parses a CoAP message Uint header option value.
|
--- Parses a CoAP message Uint header option value.
|
||||||
@@ -1490,25 +1472,15 @@ end
|
|||||||
COAP.header.options.value.uint.parse = function(buf)
|
COAP.header.options.value.uint.parse = function(buf)
|
||||||
assert(type(buf) == "string")
|
assert(type(buf) == "string")
|
||||||
assert(#buf >= 0)
|
assert(#buf >= 0)
|
||||||
assert(#buf <= 4)
|
assert(#buf <= 16)
|
||||||
|
|
||||||
if #buf == 0 then
|
if #buf == 0 then
|
||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
|
|
||||||
local val, pos
|
local val = string.unpack(">I" .. #buf, buf)
|
||||||
if #buf == 1 then
|
|
||||||
pos, val = bin.unpack("C", buf)
|
|
||||||
elseif #buf == 2 then
|
|
||||||
pos, val = bin.unpack(">S", buf)
|
|
||||||
elseif #buf == 3 then
|
|
||||||
pos, val = bin.unpack(">I", string.char(0x00) .. buf)
|
|
||||||
else
|
|
||||||
pos, val = bin.unpack(">I", buf)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- There should be no way for this to fail.
|
-- There should be no way for this to fail.
|
||||||
assert(pos)
|
|
||||||
assert(val)
|
assert(val)
|
||||||
assert(type(val) == "number")
|
assert(type(val) == "number")
|
||||||
|
|
||||||
@@ -1567,19 +1539,18 @@ COAP.header.options.delta_length.build = function(delta, length)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if num <= 268 then
|
if num <= 268 then
|
||||||
return 13, bin.pack("C", num - 13)
|
return 13, string.pack("B", num - 13)
|
||||||
end
|
end
|
||||||
|
|
||||||
return 14, bin.pack(">S", num - 269)
|
return 14, string.pack(">I2", num - 269)
|
||||||
end
|
end
|
||||||
|
|
||||||
local d1, d2 = build(delta)
|
local d1, d2 = build(delta)
|
||||||
local l1, l2 = build(length)
|
local l1, l2 = build(length)
|
||||||
|
|
||||||
d1 = d1 << 4
|
d1 = d1 << 4
|
||||||
bin.pack("C", d1 | l1)
|
|
||||||
|
|
||||||
return bin.pack("C", d1 | l1) .. d2 .. l2
|
return string.pack("B", d1 | l1) .. d2 .. l2
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Parse the variable-length option delta and length field.
|
--- Parse the variable-length option delta and length field.
|
||||||
@@ -1613,7 +1584,7 @@ COAP.header.options.delta_length.parse = function(buf, pos)
|
|||||||
assert(type(pos) == "number")
|
assert(type(pos) == "number")
|
||||||
assert(pos <= #buf)
|
assert(pos <= #buf)
|
||||||
|
|
||||||
local pos, delta_and_length = bin.unpack("C", buf, pos)
|
local delta_and_length, pos = string.unpack("B", buf, pos)
|
||||||
if not pos then
|
if not pos then
|
||||||
return false, nil, nil, delta_and_length
|
return false, nil, nil, delta_and_length
|
||||||
end
|
end
|
||||||
@@ -1636,20 +1607,20 @@ COAP.header.options.delta_length.parse = function(buf, pos)
|
|||||||
|
|
||||||
if delta == 13 then
|
if delta == 13 then
|
||||||
required_bytes = required_bytes + 1
|
required_bytes = required_bytes + 1
|
||||||
dspec = "C"
|
dspec = "B"
|
||||||
elseif delta == 14 then
|
elseif delta == 14 then
|
||||||
required_bytes = required_bytes + 2
|
required_bytes = required_bytes + 2
|
||||||
delta = 269
|
delta = 269
|
||||||
dspec = ">S"
|
dspec = ">I2"
|
||||||
end
|
end
|
||||||
|
|
||||||
if length == 13 then
|
if length == 13 then
|
||||||
required_bytes = required_bytes + 1
|
required_bytes = required_bytes + 1
|
||||||
lspec = "C"
|
lspec = "B"
|
||||||
elseif length == 14 then
|
elseif length == 14 then
|
||||||
required_bytes = required_bytes + 2
|
required_bytes = required_bytes + 2
|
||||||
length = 269
|
length = 269
|
||||||
lspec = ">S"
|
lspec = ">I2"
|
||||||
end
|
end
|
||||||
|
|
||||||
if pos + required_bytes - 1 > #buf then
|
if pos + required_bytes - 1 > #buf then
|
||||||
@@ -1659,7 +1630,7 @@ COAP.header.options.delta_length.parse = function(buf, pos)
|
|||||||
-- Extract the remaining bytes of each field.
|
-- Extract the remaining bytes of each field.
|
||||||
if dspec then
|
if dspec then
|
||||||
local num
|
local num
|
||||||
pos, num = bin.unpack(dspec, buf, pos)
|
num, pos = string.unpack(dspec, buf, pos)
|
||||||
if not pos then
|
if not pos then
|
||||||
return false, nil, nil, num
|
return false, nil, nil, num
|
||||||
end
|
end
|
||||||
@@ -1668,7 +1639,7 @@ COAP.header.options.delta_length.parse = function(buf, pos)
|
|||||||
|
|
||||||
if lspec then
|
if lspec then
|
||||||
local num
|
local num
|
||||||
pos, num = bin.unpack(lspec, buf, pos)
|
num, pos = string.unpack(lspec, buf, pos)
|
||||||
if not pos then
|
if not pos then
|
||||||
return false, nil, nil, num
|
return false, nil, nil, num
|
||||||
end
|
end
|
||||||
@@ -2426,7 +2397,7 @@ local tests = {
|
|||||||
{
|
{
|
||||||
{["name"] = "etag", ["value"] = "ETAGETAG"},
|
{["name"] = "etag", ["value"] = "ETAGETAG"},
|
||||||
},
|
},
|
||||||
bin.pack("CA", 0x48, "ETAGETAG")
|
"\x48ETAGETAG"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
-- Before
|
-- Before
|
||||||
@@ -2450,7 +2421,7 @@ local tests = {
|
|||||||
{["name"] = "uri_path", ["value"] = "foo"},
|
{["name"] = "uri_path", ["value"] = "foo"},
|
||||||
{["name"] = "max_age", ["value"] = 0},
|
{["name"] = "max_age", ["value"] = 0},
|
||||||
},
|
},
|
||||||
bin.pack("CAC", 0xB3, "foo", 0x30)
|
"\xB3foo\x30"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
-- Before
|
-- Before
|
||||||
@@ -2463,7 +2434,7 @@ local tests = {
|
|||||||
{["name"] = "uri_path", ["value"] = ".well-known"},
|
{["name"] = "uri_path", ["value"] = ".well-known"},
|
||||||
{["name"] = "uri_path", ["value"] = "core"},
|
{["name"] = "uri_path", ["value"] = "core"},
|
||||||
},
|
},
|
||||||
bin.pack("CACA", 0xBB, ".well-known", 0x04, "core")
|
"\xBB.well-known\x04core"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
-- Before
|
-- Before
|
||||||
@@ -2482,14 +2453,7 @@ local tests = {
|
|||||||
{["name"] = "uri_path", ["value"] = "core"},
|
{["name"] = "uri_path", ["value"] = "core"},
|
||||||
{["name"] = "max_age", ["value"] = 0},
|
{["name"] = "max_age", ["value"] = 0},
|
||||||
},
|
},
|
||||||
bin.pack(
|
"\x48ETAGETAG\x10\x6B.well-known\x04core\x30"
|
||||||
"CACCACAC",
|
|
||||||
0x48, "ETAGETAG", -- ID: 4, Delta: 4
|
|
||||||
0x10, -- ID: 5, Delta: 1
|
|
||||||
0x6B, ".well-known", -- ID: 11, Delta: 6
|
|
||||||
0x04, "core", -- ID: 11, Delta: 0
|
|
||||||
0x30 -- ID: 14, Delta: 3
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2537,15 +2501,7 @@ local tests = {
|
|||||||
{["name"] = "uri_path", ["value"] = "core"},
|
{["name"] = "uri_path", ["value"] = "core"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
bin.pack(
|
"\x48\x01\x12\x34nmapcoap\xBB.well-known\x04core"
|
||||||
"CC>SACACA",
|
|
||||||
0x48,
|
|
||||||
0x01,
|
|
||||||
0x1234,
|
|
||||||
"nmapcoap",
|
|
||||||
0xBB, ".well-known",
|
|
||||||
0x04, "core"
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
-- o Added possibility to override transaction id
|
-- o Added possibility to override transaction id
|
||||||
-- o Added WPAD action
|
-- o Added WPAD action
|
||||||
|
|
||||||
local bin = require "bin"
|
|
||||||
local datetime = require "datetime"
|
local datetime = require "datetime"
|
||||||
local ipOps = require "ipOps"
|
local ipOps = require "ipOps"
|
||||||
local math = require "math"
|
local math = require "math"
|
||||||
@@ -67,7 +66,7 @@ local function read_ip(data, pos, length)
|
|||||||
local results = {}
|
local results = {}
|
||||||
for i=1, length, 4 do
|
for i=1, length, 4 do
|
||||||
local value
|
local value
|
||||||
pos, value = bin.unpack(">I", data, pos)
|
value, pos = string.unpack(">I4", data, pos)
|
||||||
table.insert(results, ipOps.fromdword(value))
|
table.insert(results, ipOps.fromdword(value))
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -75,7 +74,7 @@ local function read_ip(data, pos, length)
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
local value
|
local value
|
||||||
pos, value = bin.unpack(">I", data, pos)
|
value, pos = string.unpack(">I4", data, pos)
|
||||||
|
|
||||||
return pos, ipOps.fromdword(value)
|
return pos, ipOps.fromdword(value)
|
||||||
end
|
end
|
||||||
@@ -89,7 +88,8 @@ end
|
|||||||
--@return The new position (will always be pos + length, no matter what we think it should be)
|
--@return The new position (will always be pos + length, no matter what we think it should be)
|
||||||
--@return The value of the field, or nil if the field length was wrong.
|
--@return The value of the field, or nil if the field length was wrong.
|
||||||
local function read_string(data, pos, length)
|
local function read_string(data, pos, length)
|
||||||
return bin.unpack(string.format("A%d", length), data, pos)
|
local value, pos = string.unpack(("c%d"):format(length), data, pos)
|
||||||
|
return pos, value
|
||||||
end
|
end
|
||||||
|
|
||||||
---Read a single byte. Print an error if the length isn't 1.
|
---Read a single byte. Print an error if the length isn't 1.
|
||||||
@@ -105,7 +105,8 @@ local function read_1_byte(data, pos, length)
|
|||||||
pos = pos + length
|
pos = pos + length
|
||||||
return pos, nil
|
return pos, nil
|
||||||
end
|
end
|
||||||
return bin.unpack("C", data, pos)
|
local value, pos = string.unpack("B", data, pos)
|
||||||
|
return pos, value
|
||||||
end
|
end
|
||||||
|
|
||||||
---Read a message type. This is a single-byte value that's looked up in the <code>request_types_str</code>
|
---Read a message type. This is a single-byte value that's looked up in the <code>request_types_str</code>
|
||||||
@@ -163,7 +164,8 @@ local function read_2_bytes(data, pos, length)
|
|||||||
pos = pos + length
|
pos = pos + length
|
||||||
return pos, nil
|
return pos, nil
|
||||||
end
|
end
|
||||||
return bin.unpack(">S", data, pos)
|
local value, pos = string.unpack(">I2", data, pos)
|
||||||
|
return pos, value
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -185,7 +187,7 @@ local function read_2_bytes_list(data, pos, length)
|
|||||||
local results = {}
|
local results = {}
|
||||||
for i=1, length, 2 do
|
for i=1, length, 2 do
|
||||||
local value
|
local value
|
||||||
pos, value = bin.unpack(">S", data, pos)
|
value, pos = string.unpack(">I2", data, pos)
|
||||||
table.insert(results, value)
|
table.insert(results, value)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -207,7 +209,8 @@ local function read_4_bytes(data, pos, length)
|
|||||||
pos = pos + length
|
pos = pos + length
|
||||||
return pos, nil
|
return pos, nil
|
||||||
end
|
end
|
||||||
return bin.unpack(">I", data, pos)
|
local value, pos = string.unpack(">I4", data, pos)
|
||||||
|
return pos, value
|
||||||
end
|
end
|
||||||
|
|
||||||
---Read a 4-byte unsigned little endian value, and interpret it as a time offset value. Print an
|
---Read a 4-byte unsigned little endian value, and interpret it as a time offset value. Print an
|
||||||
@@ -225,7 +228,7 @@ local function read_time(data, pos, length)
|
|||||||
pos = pos + length
|
pos = pos + length
|
||||||
return pos, nil
|
return pos, nil
|
||||||
end
|
end
|
||||||
pos, result = bin.unpack(">I", data, pos)
|
result, pos = string.unpack(">I4", data, pos)
|
||||||
|
|
||||||
return pos, datetime.format_time(result)
|
return pos, datetime.format_time(result)
|
||||||
end
|
end
|
||||||
@@ -426,34 +429,32 @@ function dhcp_build(request_type, ip_address, mac_address, options, request_opti
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Header
|
-- Header
|
||||||
packet = packet .. bin.pack(">CCCC", overrides['op'] or 1, overrides['htype'] or 1, overrides['hlen'] or 6, overrides['hops'] or 0) -- BOOTREQUEST, 10mb ethernet, 6 bytes long, 0 hops
|
packet = packet .. string.pack(">BBBB", overrides['op'] or 1, overrides['htype'] or 1, overrides['hlen'] or 6, overrides['hops'] or 0) -- BOOTREQUEST, 10mb ethernet, 6 bytes long, 0 hops
|
||||||
packet = packet .. ( overrides['xid'] or transaction_id ) -- Transaction ID =
|
packet = packet .. ( overrides['xid'] or transaction_id ) -- Transaction ID =
|
||||||
packet = packet .. bin.pack(">SS", overrides['secs'] or 0, overrides['flags'] or 0x0000) -- Secs, flags
|
packet = packet .. string.pack(">I2I2", overrides['secs'] or 0, overrides['flags'] or 0x0000) -- Secs, flags
|
||||||
packet = packet .. ip_address -- Client address
|
packet = packet .. ip_address -- Client address
|
||||||
packet = packet .. bin.pack("<I", overrides['yiaddr'] or 0) -- yiaddr
|
packet = packet .. string.pack("<I4I4I4", overrides['yiaddr'] or 0,
|
||||||
packet = packet .. bin.pack("<I", overrides['siaddr'] or 0) -- siaddr
|
overrides['siaddr'] or 0,
|
||||||
packet = packet .. bin.pack("<I", overrides['giaddr'] or 0) -- giaddr
|
overrides['giaddr'] or 0)
|
||||||
packet = packet .. mac_address .. string.rep('\0', 16 - #mac_address) -- chaddr (MAC address)
|
packet = packet .. mac_address .. string.rep('\0', 16 - #mac_address) -- chaddr (MAC address)
|
||||||
packet = packet .. (overrides['sname'] or string.rep('\0', 64)) -- sname
|
packet = packet .. (overrides['sname'] or string.rep('\0', 64)) -- sname
|
||||||
packet = packet .. (overrides['file'] or string.rep('\0', 128)) -- file
|
packet = packet .. (overrides['file'] or string.rep('\0', 128)) -- file
|
||||||
packet = packet .. bin.pack(">I", overrides['cookie'] or 0x63825363) -- Magic cookie
|
packet = packet .. string.pack(">I4", overrides['cookie'] or 0x63825363) -- Magic cookie
|
||||||
|
|
||||||
-- Options
|
-- Options
|
||||||
packet = packet .. bin.pack(">CCC", 0x35, 1, request_type) -- Request type
|
packet = packet .. string.pack(">BBB", 0x35, 1, request_type) -- Request type
|
||||||
|
|
||||||
for _, option in ipairs(options or {}) do
|
for _, option in ipairs(options or {}) do
|
||||||
packet = packet .. bin.pack(">C", option.number)
|
packet = packet .. string.pack(">B", option.number)
|
||||||
if ( "string" == option.type ) then
|
if ( "string" == option.type or "ip" == option.type ) then
|
||||||
packet = packet .. bin.pack("p", option.value)
|
packet = packet .. string.pack("s1", option.value)
|
||||||
elseif( "ip" == option.type ) then
|
|
||||||
packet = packet .. bin.pack(">CI", 4, option.value)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
packet = packet .. bin.pack(">CCA", 0x37, #request_options, request_options) -- Request options
|
packet = packet .. string.pack(">Bs1", 0x37, request_options) -- Request options
|
||||||
packet = packet .. bin.pack(">CCI", 0x33, 4, lease_time or 1) -- Lease time
|
packet = packet .. string.pack(">BBI4", 0x33, 4, lease_time or 1) -- Lease time
|
||||||
|
|
||||||
packet = packet .. bin.pack(">C", 0xFF) -- Termination
|
packet = packet .. "\xFF" -- Termination
|
||||||
|
|
||||||
return true, strbuf.dump(packet)
|
return true, strbuf.dump(packet)
|
||||||
end
|
end
|
||||||
@@ -473,26 +474,26 @@ function dhcp_parse(data, transaction_id)
|
|||||||
local result = {}
|
local result = {}
|
||||||
|
|
||||||
-- Receive the first bit and make sure we got the correct operation back
|
-- Receive the first bit and make sure we got the correct operation back
|
||||||
pos, result['op'], result['htype'], result['hlen'], result['hops'] = bin.unpack(">CCCC", data, pos)
|
result.op, result.htype, result.hlen, result.hops, pos = string.unpack(">BBBB", data, pos)
|
||||||
if(result['op'] ~= 2) then
|
if(result['op'] ~= 2) then
|
||||||
return false, string.format("DHCP server returned invalid reply ('op' wasn't BOOTREPLY (it was 0x%02x))", result['op'])
|
return false, string.format("DHCP server returned invalid reply ('op' wasn't BOOTREPLY (it was 0x%02x))", result['op'])
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Confirm the transaction id
|
-- Confirm the transaction id
|
||||||
pos, result['xid'] = bin.unpack("A4", data, pos)
|
result.xid, pos = string.unpack("c4", data, pos)
|
||||||
if(result['xid'] ~= transaction_id) then
|
if(result['xid'] ~= transaction_id) then
|
||||||
return false, string.format("DHCP server returned invalid reply (transaction id didn't match (%s != %s))", result['xid'], transaction_id)
|
return false, string.format("DHCP server returned invalid reply (transaction id didn't match (%s != %s))", result['xid'], transaction_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Unpack the secs, flags, addresses, sname, and file
|
-- Unpack the secs, flags, addresses, sname, and file
|
||||||
pos, result['secs'], result['flags'] = bin.unpack(">SS", data, pos)
|
result.secs, result.flags,
|
||||||
pos, result['ciaddr'] = bin.unpack(">I", data, pos)
|
result.ciaddr,
|
||||||
pos, result['yiaddr'] = bin.unpack(">I", data, pos)
|
result.yiaddr,
|
||||||
pos, result['siaddr'] = bin.unpack(">I", data, pos)
|
result.siaddr,
|
||||||
pos, result['giaddr'] = bin.unpack(">I", data, pos)
|
result.giaddr,
|
||||||
pos, result['chaddr'] = bin.unpack("A16", data, pos)
|
result.chaddr,
|
||||||
pos, result['sname'] = bin.unpack("A64", data, pos)
|
result.sname,
|
||||||
pos, result['file'] = bin.unpack("A128", data, pos)
|
result.file, pos = string.unpack(">I2I2 I4I4I4I4 c16 c64 c128", data, pos)
|
||||||
|
|
||||||
-- Convert the addresses to strings
|
-- Convert the addresses to strings
|
||||||
result['ciaddr_str'] = ipOps.fromdword(result['ciaddr'])
|
result['ciaddr_str'] = ipOps.fromdword(result['ciaddr'])
|
||||||
@@ -501,7 +502,7 @@ function dhcp_parse(data, transaction_id)
|
|||||||
result['giaddr_str'] = ipOps.fromdword(result['giaddr'])
|
result['giaddr_str'] = ipOps.fromdword(result['giaddr'])
|
||||||
|
|
||||||
-- Confirm the cookie
|
-- Confirm the cookie
|
||||||
pos, result['cookie'] = bin.unpack(">I", data, pos)
|
result.cookie, pos = string.unpack(">I4", data, pos)
|
||||||
if(result['cookie'] ~= 0x63825363) then
|
if(result['cookie'] ~= 0x63825363) then
|
||||||
return false, "DHCP server returned invalid reply (the magic cookie was invalid)"
|
return false, "DHCP server returned invalid reply (the magic cookie was invalid)"
|
||||||
end
|
end
|
||||||
@@ -515,7 +516,7 @@ function dhcp_parse(data, transaction_id)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local option, length
|
local option, length
|
||||||
pos, option, length = bin.unpack(">CC", data, pos)
|
option, length, pos = string.unpack(">BB", data, pos)
|
||||||
|
|
||||||
-- Check for termination condition
|
-- Check for termination condition
|
||||||
if(option == 0xFF) then
|
if(option == 0xFF) then
|
||||||
@@ -611,10 +612,10 @@ end
|
|||||||
--@return The parsed response, as a table.
|
--@return The parsed response, as a table.
|
||||||
function make_request(target, request_type, ip_address, mac_address, options, request_options, overrides, lease_time)
|
function make_request(target, request_type, ip_address, mac_address, options, request_options, overrides, lease_time)
|
||||||
-- A unique id that identifies this particular session (and lets us filter out what we don't want to see)
|
-- A unique id that identifies this particular session (and lets us filter out what we don't want to see)
|
||||||
local transaction_id = overrides and overrides['xid'] or bin.pack("<I", math.random(0, 0x7FFFFFFF))
|
local transaction_id = overrides and overrides['xid'] or string.pack("<I4", math.random(0, 0x7FFFFFFF))
|
||||||
|
|
||||||
-- Generate the packet
|
-- Generate the packet
|
||||||
local status, packet = dhcp_build(request_type, bin.pack(">I", ipOps.todword(ip_address)), mac_address, options, request_options, overrides, lease_time, transaction_id)
|
local status, packet = dhcp_build(request_type, ipOps.ip_to_str(ip_address), mac_address, options, request_options, overrides, lease_time, transaction_id)
|
||||||
if(not(status)) then
|
if(not(status)) then
|
||||||
stdnse.debug1("dhcp: Couldn't build packet: " .. packet)
|
stdnse.debug1("dhcp: Couldn't build packet: " .. packet)
|
||||||
return false, "Couldn't build packet: " .. packet
|
return false, "Couldn't build packet: " .. packet
|
||||||
|
|||||||
@@ -920,7 +920,8 @@ MQTT.utf8_parse = function(buf, pos)
|
|||||||
return false, ("Buffer at position %d has no space for a %d-byte UTF-8 string."):format(pos, str_length)
|
return false, ("Buffer at position %d has no space for a %d-byte UTF-8 string."):format(pos, str_length)
|
||||||
end
|
end
|
||||||
|
|
||||||
return string.unpack(">s2", buf, pos)
|
local value, pos = string.unpack(">s2", buf, pos)
|
||||||
|
return pos, value
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Prefix the body of an MQTT packet with a fixed header.
|
--- Prefix the body of an MQTT packet with a fixed header.
|
||||||
|
|||||||
114
nselib/mysql.lua
114
nselib/mysql.lua
@@ -7,7 +7,6 @@
|
|||||||
--
|
--
|
||||||
-- @author Patrik Karlsson <patrik@cqure.net>
|
-- @author Patrik Karlsson <patrik@cqure.net>
|
||||||
|
|
||||||
local bin = require "bin"
|
|
||||||
local nmap = require "nmap"
|
local nmap = require "nmap"
|
||||||
local stdnse = require "stdnse"
|
local stdnse = require "stdnse"
|
||||||
local string = require "string"
|
local string = require "string"
|
||||||
@@ -91,7 +90,7 @@ local function decodeHeader( data, pos )
|
|||||||
local response = {}
|
local response = {}
|
||||||
local pos, tmp = pos or 1, 0
|
local pos, tmp = pos or 1, 0
|
||||||
|
|
||||||
pos, tmp = bin.unpack( "<I", data, pos )
|
tmp, pos = string.unpack( "<I4", data, pos )
|
||||||
response.len = ( tmp & 255 )
|
response.len = ( tmp & 255 )
|
||||||
response.number = ( tmp >> 24 )
|
response.number = ( tmp >> 24 )
|
||||||
|
|
||||||
@@ -121,42 +120,38 @@ function receiveGreeting( socket )
|
|||||||
end
|
end
|
||||||
|
|
||||||
local is_error
|
local is_error
|
||||||
pos, is_error = bin.unpack( "C", data, pos )
|
is_error, pos = string.unpack("B", data, pos)
|
||||||
|
|
||||||
if ( is_error == 0xff ) then
|
if ( is_error == 0xff ) then
|
||||||
pos, response.errorcode = bin.unpack( "<S", data, pos )
|
response.errorcode, pos = string.unpack( "<I2", data, pos )
|
||||||
pos, response.errormsg = bin.unpack("A" .. (#data - pos + 1), data, pos )
|
response.errormsg = data:sub(pos)
|
||||||
|
|
||||||
return false, response.errormsg
|
return false, response.errormsg
|
||||||
end
|
end
|
||||||
|
|
||||||
response.proto = is_error
|
response.proto = is_error
|
||||||
pos, response.version = bin.unpack( "z", data, pos )
|
response.version, response.threadid, pos = string.unpack( "<zI4", data, pos )
|
||||||
pos, response.threadid = bin.unpack( "<I", data, pos )
|
|
||||||
|
|
||||||
if response.proto == 10 then
|
if response.proto == 10 then
|
||||||
pos, response.salt, _ = bin.unpack( "A8C", data, pos )
|
response.salt, response.capabilities, pos = string.unpack("<c8xI2", data, pos)
|
||||||
pos, response.capabilities = bin.unpack( "<S", data, pos )
|
|
||||||
if pos < #data then
|
|
||||||
pos, response.charset = bin.unpack( "C", data, pos )
|
|
||||||
pos, response.status = bin.unpack( "<S", data, pos )
|
|
||||||
pos, response.extcapabilities = bin.unpack( "<S", data, pos) -- capabilities, upper 2 bytes
|
|
||||||
local auth_plugin_len
|
local auth_plugin_len
|
||||||
pos, auth_plugin_len = bin.unpack("C", data, pos)
|
if pos < #data then
|
||||||
pos, tmp = bin.unpack( "A10", data, pos )
|
response.charset, response.status,
|
||||||
|
response.extcapabilities, -- capabilities, upper 2 bytes
|
||||||
|
auth_plugin_len, tmp, pos = string.unpack( "<BI2 I2 Bc10", data, pos )
|
||||||
if tmp ~= "\0\0\0\0\0\0\0\0\0\0" then
|
if tmp ~= "\0\0\0\0\0\0\0\0\0\0" then
|
||||||
stdnse.debug2("reserved bytes are not nulls")
|
stdnse.debug2("reserved bytes are not nulls")
|
||||||
end
|
end
|
||||||
if response.capabilities & Capabilities.Support41Auth > 0 then
|
if response.capabilities & Capabilities.Support41Auth > 0 then
|
||||||
pos, tmp, _ = bin.unpack("A" .. (math.max(13, auth_plugin_len - 8) - 1) .. "x", data, pos)
|
tmp, pos = string.unpack("c" .. (math.max(13, auth_plugin_len - 8) - 1) .. "x", data, pos)
|
||||||
response.salt = response.salt .. tmp
|
response.salt = response.salt .. tmp
|
||||||
end
|
end
|
||||||
if response.extcapabilities & ExtCapabilities.SupportsAuthPlugins > 0 then
|
if response.extcapabilities & ExtCapabilities.SupportsAuthPlugins > 0 then
|
||||||
response.auth_plugin_name = bin.unpack("z", data, pos)
|
response.auth_plugin_name = string.unpack("z", data, pos)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif response.proto == 9 then
|
elseif response.proto == 9 then
|
||||||
pos, response.auth_plugin_data = bin.unpack( "z", data, pos )
|
response.auth_plugin_data, pos = string.unpack( "z", data, pos )
|
||||||
else
|
else
|
||||||
stdnse.debug2("Unknown MySQL protocol version: %d", response.proto)
|
stdnse.debug2("Unknown MySQL protocol version: %d", response.proto)
|
||||||
end
|
end
|
||||||
@@ -189,8 +184,8 @@ local function createLoginHash(pass, salt)
|
|||||||
hash_stage3 = openssl.sha1( salt .. hash_stage2 )
|
hash_stage3 = openssl.sha1( salt .. hash_stage2 )
|
||||||
|
|
||||||
for pos=1, hash_stage1:len() do
|
for pos=1, hash_stage1:len() do
|
||||||
_, b1 = bin.unpack( "C", hash_stage1, pos )
|
b1 = string.unpack( "B", hash_stage1, pos )
|
||||||
_, b2 = bin.unpack( "C", hash_stage3, pos )
|
b2 = string.unpack( "B", hash_stage3, pos )
|
||||||
|
|
||||||
reply[pos] = string.char( b2 ~ b1 )
|
reply[pos] = string.char( b2 ~ b1 )
|
||||||
end
|
end
|
||||||
@@ -244,7 +239,7 @@ function loginRequest( socket, params, username, password, salt )
|
|||||||
hash = createLoginHash( password, salt )
|
hash = createLoginHash( password, salt )
|
||||||
end
|
end
|
||||||
|
|
||||||
local packet = bin.pack( "<SSICAzp",
|
local packet = string.pack( "<I2I2I4B c23 zs1",
|
||||||
clicap,
|
clicap,
|
||||||
extcapabilities,
|
extcapabilities,
|
||||||
MAXPACKET,
|
MAXPACKET,
|
||||||
@@ -256,7 +251,7 @@ function loginRequest( socket, params, username, password, salt )
|
|||||||
|
|
||||||
local tmp = packet:len() + ( packetno << 24 )
|
local tmp = packet:len() + ( packetno << 24 )
|
||||||
|
|
||||||
packet = bin.pack( "<I", tmp ) .. packet
|
packet = string.pack( "<I4", tmp ) .. packet
|
||||||
|
|
||||||
try( socket:send(packet) )
|
try( socket:send(packet) )
|
||||||
packet = try( socket:receive_bytes(HEADER_SIZE) )
|
packet = try( socket:receive_bytes(HEADER_SIZE) )
|
||||||
@@ -270,26 +265,24 @@ function loginRequest( socket, params, username, password, salt )
|
|||||||
|
|
||||||
local is_error
|
local is_error
|
||||||
|
|
||||||
pos, is_error = bin.unpack( "C", packet, pos )
|
is_error, pos = string.unpack( "B", packet, pos )
|
||||||
|
|
||||||
if is_error > 0 then
|
if is_error > 0 then
|
||||||
pos, response.errorcode = bin.unpack( "<S", packet, pos )
|
|
||||||
|
|
||||||
local has_sqlstate
|
local has_sqlstate
|
||||||
pos, has_sqlstate = bin.unpack( "C", packet, pos )
|
response.errorcode, has_sqlstate, pos = string.unpack( "<I2B", packet, pos )
|
||||||
|
|
||||||
if has_sqlstate == 35 then
|
if has_sqlstate == 35 then
|
||||||
pos, response.sqlstate = bin.unpack( "A5", packet, pos )
|
response.sqlstate, pos = string.unpack( "c5", packet, pos )
|
||||||
end
|
end
|
||||||
|
|
||||||
pos, response.errormessage = bin.unpack( "z", packet, pos )
|
response.errormessage, pos = string.unpack( "z", packet, pos )
|
||||||
|
|
||||||
return false, response.errormessage
|
return false, response.errormessage
|
||||||
else
|
else
|
||||||
response.errorcode = 0
|
response.errorcode = 0
|
||||||
pos, response.affectedrows = bin.unpack( "C", packet, pos )
|
response.affectedrows,
|
||||||
pos, response.serverstatus = bin.unpack( "<S", packet, pos )
|
response.serverstatus,
|
||||||
pos, response.warnings = bin.unpack( "<S", packet, pos )
|
response.warnings, pos = string.unpack( "<BI2I2", packet, pos )
|
||||||
end
|
end
|
||||||
|
|
||||||
return true, response
|
return true, response
|
||||||
@@ -309,36 +302,19 @@ end
|
|||||||
-- <code>length</code> and <code>type</code>
|
-- <code>length</code> and <code>type</code>
|
||||||
function decodeField( data, pos )
|
function decodeField( data, pos )
|
||||||
|
|
||||||
local header, len
|
local _
|
||||||
local def, _
|
|
||||||
local field = {}
|
local field = {}
|
||||||
|
|
||||||
pos, len = bin.unpack( "C", data, pos )
|
field.catalog,
|
||||||
pos, field.catalog = bin.unpack( "A" .. len, data, pos )
|
field.database,
|
||||||
|
field.table,
|
||||||
pos, len = bin.unpack( "C", data, pos )
|
field.orig_table,
|
||||||
pos, field.database = bin.unpack( "A" .. len, data, pos )
|
field.name,
|
||||||
|
field.orig_name,
|
||||||
pos, len = bin.unpack( "C", data, pos )
|
_, -- should be 0x0C
|
||||||
pos, field.table = bin.unpack( "A" .. len, data, pos )
|
_, -- charset, in my case 0x0800
|
||||||
|
field.length,
|
||||||
pos, len = bin.unpack( "C", data, pos )
|
field.type, pos = string.unpack( "<s1s1s1s1s1s1BI2I4c6", data, pos )
|
||||||
pos, field.orig_table = bin.unpack( "A" .. len, data, pos )
|
|
||||||
|
|
||||||
pos, len = bin.unpack( "C", data, pos )
|
|
||||||
pos, field.name = bin.unpack( "A" .. len, data, pos )
|
|
||||||
|
|
||||||
pos, len = bin.unpack( "C", data, pos )
|
|
||||||
pos, field.orig_name = bin.unpack( "A" .. len, data, pos )
|
|
||||||
|
|
||||||
-- should be 0x0C
|
|
||||||
pos, _ = bin.unpack( "C", data, pos )
|
|
||||||
|
|
||||||
-- charset, in my case 0x0800
|
|
||||||
pos, _ = bin.unpack( "<S", data, pos )
|
|
||||||
|
|
||||||
pos, field.length = bin.unpack( "<I", data, pos )
|
|
||||||
pos, field.type = bin.unpack( "A6", data, pos )
|
|
||||||
|
|
||||||
return pos, field
|
return pos, field
|
||||||
|
|
||||||
@@ -403,7 +379,7 @@ function decodeQueryResponse( socket )
|
|||||||
end
|
end
|
||||||
|
|
||||||
if header.len > 0 then
|
if header.len > 0 then
|
||||||
local _, b = bin.unpack("C", data, pos )
|
local b = string.unpack("B", data, pos )
|
||||||
|
|
||||||
-- Is this the EOF packet?
|
-- Is this the EOF packet?
|
||||||
if b == EOF_MARKER then
|
if b == EOF_MARKER then
|
||||||
@@ -465,13 +441,11 @@ end
|
|||||||
-- @return number containing the amount of fields
|
-- @return number containing the amount of fields
|
||||||
function decodeResultSetHeader( data )
|
function decodeResultSetHeader( data )
|
||||||
|
|
||||||
local _, fields
|
|
||||||
|
|
||||||
if data:len() ~= HEADER_SIZE + 1 then
|
if data:len() ~= HEADER_SIZE + 1 then
|
||||||
return false, "Result set header was incorrect"
|
return false, "Result set header was incorrect"
|
||||||
end
|
end
|
||||||
|
|
||||||
_, fields = bin.unpack( "C", data, HEADER_SIZE + 1 )
|
local fields = string.unpack( "B", data, HEADER_SIZE + 1 )
|
||||||
|
|
||||||
return true, fields
|
return true, fields
|
||||||
end
|
end
|
||||||
@@ -486,16 +460,16 @@ end
|
|||||||
-- @return rows table containing row tables
|
-- @return rows table containing row tables
|
||||||
function decodeDataPackets( data, count )
|
function decodeDataPackets( data, count )
|
||||||
|
|
||||||
local len, pos = 0, 1, 1
|
local pos = 1
|
||||||
local header, row, rows = {}, {}, {}
|
local rows = {}
|
||||||
|
|
||||||
while pos < data:len() do
|
while pos <= data:len() do
|
||||||
row = {}
|
local row = {}
|
||||||
|
local header
|
||||||
pos, header = decodeHeader( data, pos )
|
pos, header = decodeHeader( data, pos )
|
||||||
|
|
||||||
for i=1, count do
|
for i=1, count do
|
||||||
pos, len = bin.unpack("C", data, pos )
|
row[i], pos = string.unpack("s1", data, pos)
|
||||||
pos, row[i] = bin.unpack("A" .. len, data, pos)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert( rows, row )
|
table.insert( rows, row )
|
||||||
@@ -521,7 +495,7 @@ function sqlQuery( socket, query )
|
|||||||
local packet, packet_len, pos, header
|
local packet, packet_len, pos, header
|
||||||
local status, fields, field_count, rows, rs
|
local status, fields, field_count, rows, rs
|
||||||
|
|
||||||
packet = bin.pack("<ICA", querylen, Command.Query, query )
|
packet = string.pack("<I4B", querylen, Command.Query) .. query
|
||||||
|
|
||||||
--
|
--
|
||||||
-- http://forge.mysql.com/wiki/MySQL_Internals_ClientServer_Protocol#Result_Set_Header_Packet
|
-- http://forge.mysql.com/wiki/MySQL_Internals_ClientServer_Protocol#Result_Set_Header_Packet
|
||||||
|
|||||||
Reference in New Issue
Block a user