diff --git a/nselib/drda.lua b/nselib/drda.lua
index e1a5de09c..add96201c 100644
--- a/nselib/drda.lua
+++ b/nselib/drda.lua
@@ -60,6 +60,7 @@
local bin = require "bin"
local bit = require "bit"
+local match = require "match"
local nmap = require "nmap"
local stdnse = require "stdnse"
local string = require "string"
@@ -120,11 +121,12 @@ SecMec =
DRDAPacket = {
new = function(self, drda_array)
- local o = {}
- setmetatable(o, self)
- self.__index = self
- o.drda_array = drda_array
- o.count = #drda_array
+ local o = {
+ drda_array = drda_array,
+ count = #drda_array
+ }
+ setmetatable(o, self)
+ self.__index = self
return o
end,
@@ -161,11 +163,12 @@ DRDAPacket = {
DRDA = {
new = function(self, ddm)
- local o = {}
- setmetatable(o, self)
- self.__index = self
- o.Parameters = {}
- o.DDM = ddm
+ local o = {
+ Parameters = {},
+ DDM = ddm
+ }
+ setmetatable(o, self)
+ self.__index = self
return o
end,
@@ -256,7 +259,7 @@ DRDA = {
local pos = 1
-- first read atleast enough so that we can populate the DDM
- status, data = db2socket:recv( DDM_SIZE )
+ status, data = db2socket:receive_buf( match.numbytes(DDM_SIZE), true )
if ( not(status) ) then
stdnse.print_debug("drda.DRDA.receive: %s", data)
return false, ("Failed to read at least %d bytes from socket"):format(DDM_SIZE)
@@ -266,7 +269,7 @@ DRDA = {
ddm:fromString( data )
self:setDDM( ddm )
- status, data = db2socket:recv( ddm.Length - 10 )
+ status, data = db2socket:receive_buf( match.numbytes(ddm.Length - 10), true )
if ( not(status) ) then
return false, ("Failed to read the remaining %d bytes of the DRDA message")
end
@@ -292,16 +295,13 @@ DRDAParameter = {
-- @param data string containing the data portion of the DRDA parameter
-- @return o DRDAParameter object
new = function(self, codepoint, data)
- local o = {}
- setmetatable(o, self)
- self.__index = self
- o.CodePoint = codepoint
- if ( data ) then
- o.Data = data
- o.Length = #o.Data + 4
- else
- o.Length = 4
- end
+ local o = {
+ CodePoint = codepoint,
+ Data = data,
+ Length = ( data and #data + 4 or 4 )
+ }
+ setmetatable(o, self)
+ self.__index = self
return o
end,
@@ -378,16 +378,13 @@ DDM = {
-- @param corelid
-- @return DDM object
new = function(self, codepoint, format, corelid)
- local o = {}
- setmetatable(o, self)
- self.__index = self
- o.CodePoint = codepoint
- if ( format ) then
- o.Format = format
- end
- if ( corelid ) then
- o.CorelId = corelid
- end
+ local o = {
+ CodePoint = codepoint,
+ Format = format,
+ CorelId = corelid
+ }
+ setmetatable(o, self)
+ self.__index = self
return o
end,
@@ -529,8 +526,8 @@ Helper = {
new = function(self)
local o = {}
- setmetatable(o, self)
- self.__index = self
+ setmetatable(o, self)
+ self.__index = self
return o
end,
@@ -541,9 +538,8 @@ Helper = {
-- @return Status (true or false).
-- @return Error code (if status is false).
connect = function( self, host, port )
- self.db2socket = DB2Socket:new()
- self.comm = Comm:new( self.db2socket )
- return self.db2socket:connect(host, port)
+ self.comm = Comm:new( host, port )
+ return self.comm:connect()
end,
--- Closes an open connection.
@@ -551,7 +547,7 @@ Helper = {
-- @return Status (true or false).
-- @return Error code (if status is false).
close = function( self )
- self.db2socket:close()
+ self.comm:close()
end,
--- Returns Server Information (name, platform, version)
@@ -676,14 +672,41 @@ Helper = {
-- The communication class
Comm = {
- new = function(self, socket)
- local o = {}
- setmetatable(o, self)
- self.__index = self
- o.socket = socket
+ new = function(self, host, port)
+ local o = {
+ host = host,
+ port = port,
+ socket = nmap.new_socket()
+ }
+ setmetatable(o, self)
+ self.__index = self
return o
end,
+ connect = function(self)
+ return self.socket:connect(self.host, self.port)
+ end,
+
+ close = function(self)
+ return self.socket:close()
+ end,
+
+ recvDRDA = function( self )
+ local status, err
+ local drda_tbl = {}
+
+ repeat
+ local drda = DRDA:new()
+ status, err = drda:receive( self.socket )
+ if ( not(status) ) then
+ return false, err
+ end
+ table.insert(drda_tbl, drda)
+ until ( not(drda.DDM:isChained()) )
+
+ return true, drda_tbl
+ end,
+
--- Sends a packet to the server and receives the response
--
-- @param DRDAPacket
@@ -691,14 +714,14 @@ Comm = {
-- @return packet an instance of DRDAPacket
exchDRDAPacket = function( self, packet )
local drda, err
- local status, err = self.socket:sendDRDA( packet )
+ local status, err = self.socket:send( tostring(packet) )
if ( not(status) ) then
stdnse.print_debug("drda.Helper.login: ERROR: DB2Socket error: %s", err )
return false, ("ERROR: DB2Socket error: %s"):format( err )
end
- status, drda = self.socket:recvDRDA()
+ status, drda = self:recvDRDA()
if( not(status) ) then
stdnse.print_debug("drda.Helper.login: ERROR: DB2Socket error: %s", drda )
return false, ("ERROR: DB2Socket error: %s"):format( drda )
@@ -710,117 +733,6 @@ Comm = {
}
--- The DB2Socket class
---
--- Allows for reading an exact count of bytes opposed to the nmap socket
--- implementation that does at least count of bytes.
---
--- The DB2Socket makes use of nmaps underlying socket implementation and
--- buffers the bytes exceeding the number asked for. The next call to the
--- recv function will fetch bytes from the buffer and call
--- the recieve_bytes function of the underlying when there
--- are no more buffered bytes.
---
--- The connect, close and send
--- functions are wrappers around the same functions of the nmap socket code.
--- Consult the nsedoc for additional information on these.
-DB2Socket = {
-
- retries = 3,
-
- new = function(self)
- local o = {}
- setmetatable(o, self)
- self.__index = self
- o.Socket = nmap.new_socket()
- o.Buffer = nil
- return o
- end,
-
-
- --- Establishes a connection.
- --
- -- @param hostid Host table, hostname, or IP address.
- -- @param port Port table or number.
- -- @param protocol "tcp", "udp", or
- -- @return Status (true or false).
- -- @return Error code (if status is false).
- connect = function( self, hostid, port, protocol )
- return self.Socket:connect( hostid, port, protocol )
- end,
-
- --- Closes an open connection.
- --
- -- @return Status (true or false).
- -- @return Error code (if status is false).
- close = function( self )
- return self.Socket:close()
- end,
-
- --- Opposed to the socket:receive_bytes function, that returns
- -- at least x bytes, this function returns the amount of bytes requested.
- --
- -- @param count of bytes to read
- -- @return true on success, false on failure
- -- @return data containing bytes read from the socket
- -- err containing error message if status is false
- recv = function( self, count )
- local status, data
-
- self.Buffer = self.Buffer or ""
-
- if ( #self.Buffer < count ) then
- status, data = self.Socket:receive_bytes( count - #self.Buffer )
- if ( not(status) or #data < count - #self.Buffer ) then
- return false, data
- end
- self.Buffer = self.Buffer .. data
- end
-
- data = self.Buffer:sub( 1, count )
- self.Buffer = self.Buffer:sub( count + 1)
-
- return true, data
- end,
-
- --- Sends data over the socket
- --
- -- @return Status (true or false).
- -- @return Error code (if status is false).
- send = function( self, data )
- return self.Socket:send( data )
- end,
-
- --- Sends a single or multiple DRDA's over the socket
- --
- -- @param drda a single or a table containing multiple DRDA's
- -- @return Status (true or false).
- -- @return Error code (if status is false).
- sendDRDA = function( self, drda )
- return self:send(tostring(drda))
- end,
-
- --- Reads a single or multiple DRDA's of the socket
- --
- -- @return status (true or false)
- -- @return drda table containing retrieved DRDA's
- recvDRDA = function( self )
- local status, err
- local drda_tbl = {}
-
- repeat
- local drda = DRDA:new()
- status, err = drda:receive( self )
- if ( not(status) ) then
- return false, err
- end
- table.insert(drda_tbl, drda)
- until ( not(drda.DDM:isChained()) )
-
- return true, drda_tbl
- end,
-}
-
-- EBCDIC/ASCII Conversion tables
a2e_hex = "00010203372D2E2F1605250B0C0D0E0F101112133C3D322618193F271C1D1E1F"
a2e_hex = a2e_hex .. "405A7F7B5B6C507D4D5D5C4E6B604B61F0F1F2F3F4F5F6F7F8F97A5E4C7E6E6F"