diff --git a/nselib/amqp.lua b/nselib/amqp.lua index aa2a741d5..5804ba608 100644 --- a/nselib/amqp.lua +++ b/nselib/amqp.lua @@ -13,8 +13,6 @@ -- o AMQP -- - This class contains the core functions needed to communicate with AMQP -- --- o AMQPSocket --- - This is a copy of the VNCSocket class. -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html -- @author "Sebastian Dragomir " @@ -24,6 +22,7 @@ -- Created 05/04/2011 - v0.1 - created by Sebastian Dragomir local bin = require "bin" +local match = require "match" local nmap = require "nmap" local stdnse = require "stdnse" local string = require "string" @@ -52,7 +51,7 @@ AMQP = { self.__index = self o.host = host o.port = port - o.amqpsocket = AMQPSocket:new() + o.amqpsocket = nmap.new_socket() o.cli_version = self.client_version_strings[nmap.registry.args['amqp.version']] or self.client_version_strings["0-9-1"] o.protover = nil o.server_version = nil @@ -88,27 +87,27 @@ AMQP = { while read < tsize do local key, value - status, tmp = self.amqpsocket:recv( 1 ) + status, tmp = self.amqpsocket:receive_buf(match.numbytes(1), true) if ( not(status) ) then return status, "ERROR: AMQP:handshake connection closed unexpectedly while reading key length", nil end read = read + 1 tmp = select( 2, bin.unpack("C", tmp) ) - status, key = self.amqpsocket:recv( tmp ) + status, key = self.amqpsocket:receive_buf(match.numbytes(tmp), true) if ( not(status) ) then return status, "ERROR: AMQP:handshake connection closed unexpectedly while reading key", nil end read = read + tmp - status, tmp = self.amqpsocket:recv( 1 ) + status, tmp = self.amqpsocket:receive_buf(match.numbytes(1), true) if ( not(status) ) then return status, "ERROR: AMQP:handshake connection closed unexpectedly while reading value type for " .. key, nil end read = read + 1 if ( tmp == 'F' ) then -- table type - status, tmp = self.amqpsocket:recv( 4 ) + status, tmp = self.amqpsocket:receive_buf(match.numbytes(4), true) if ( not(status) ) then return status, "ERROR: AMQP:handshake connection closed unexpectedly while reading table size", nil end @@ -152,14 +151,14 @@ AMQP = { -- @return number of bytes read after decoding this value decodeString = function(self, key, read) local value, status, tmp - status, tmp = self.amqpsocket:recv( 4 ) + status, tmp = self.amqpsocket:receive_buf(match.numbytes(4), true) if ( not(status) ) then return status, "ERROR: AMQP:handshake connection closed unexpectedly while reading value size for " .. key, nil, 0 end read = read + 4 tmp = select( 2, bin.unpack(">I", tmp) ) - status, value = self.amqpsocket:recv( tmp ) + status, value = self.amqpsocket:receive_buf(match.numbytes(tmp), true) if ( not(status) ) then return status, "ERROR: AMQP:handshake connection closed unexpectedly while reading value for " .. key, nil, 0 @@ -179,7 +178,7 @@ AMQP = { -- @return number of bytes read after decoding this value decodeBoolean = function(self, key, read) local status, value - status, value = self.amqpsocket:recv( 1 ) + status, value = self.amqpsocket:receive_buf(match.numbytes(1), true) if ( not(status) ) then return status, "ERROR: AMQP:handshake connection closed unexpectedly while reading value for " .. key, nil, 0 end @@ -204,7 +203,7 @@ AMQP = { return false, "ERROR: AMQP:handshake failed while sending client version" end - status, tmp = self.amqpsocket:recv( 11 ) + status, tmp = self.amqpsocket:receive_buf(match.numbytes(11), true) if ( not(status) ) then return status, "ERROR: AMQP:handshake connection closed unexpectedly while reading frame header" end @@ -261,7 +260,7 @@ AMQP = { end -- parse protocol version - status, tmp = self.amqpsocket:recv( 2 ) + status, tmp = self.amqpsocket:receive_buf(match.num_bytes(2), true) if ( not(status) ) then return status, "ERROR: AMQP:handshake connection closed unexpectedly while reading version" end @@ -273,7 +272,7 @@ AMQP = { end -- parse server properties - status, tmp = self.amqpsocket:recv( 4 ) + status, tmp = self.amqpsocket:receive_buf(match.numbytes(4), true) if ( not(status) ) then return status, "ERROR: AMQP:handshake connection closed unexpectedly while reading server properties size" end @@ -332,72 +331,4 @@ AMQP = { end, } -AMQPSocket = -{ - 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 Hostname or IP address. - -- @param port Port 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 ) - self.Buffer = nil - 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) ) 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, -} - return _ENV; diff --git a/nselib/bitcoin.lua b/nselib/bitcoin.lua index 330167ef9..5d3cd3dd1 100644 --- a/nselib/bitcoin.lua +++ b/nselib/bitcoin.lua @@ -16,8 +16,6 @@ -- o Addr - The server address packet -- o Inv - The server inventory packet -- --- * BCSocket - A buffering socket class --- -- * Helper - The primary interface to scripts -- --@author Patrik Karlsson @@ -34,6 +32,7 @@ local bin = require "bin" local ipOps = require "ipOps" +local match = require "match" local nmap = require "nmap" local os = require "os" local stdnse = require "stdnse" @@ -371,13 +370,13 @@ Response = { }, -- Receives the packet and decodes it - -- @param socket BCSocket instance + -- @param socket socket connected to the server -- @param version number containing the server version -- @return status true on success, false on failure -- @return response instance of response packet if status is true -- err string containing the error message if status is false recvPacket = function(socket, version) - local status, header = socket:recv(24) + local status, header = socket:receive_buf(match.numbytes(24), true) if ( not(status) ) then return false, "Failed to read the packet header" end @@ -387,7 +386,7 @@ Response = { -- the verack has no payload if ( 0 ~= len ) then - status, data = socket:recv(len) + status, data = socket:receive_buf(match.numbytes(len), true) if ( not(status) ) then return false, "Failed to read the packet header" end @@ -442,82 +441,6 @@ Util = { } --- A buffered socket implementation -BCSocket = -{ - retries = 3, - - -- Creates a new BCSocket instance - -- @param host table as received by the action method - -- @param port table as received by the action method - -- @param options table containing additional options - -- timeout - the socket timeout in ms - -- @return instance of BCSocket - new = function(self, host, port, options) - local o = { - host = host, - port = port, - timeout = "table" == type(options) and options.timeout or 10000 - } - setmetatable(o, self) - self.__index = self - o.Socket = nmap.new_socket() - o.Buffer = nil - return o - end, - - --- Establishes a connection. - -- - -- @return Status (true or false). - -- @return Error code (if status is false). - connect = function( self ) - self.Socket:set_timeout( self.timeout ) - return self.Socket:connect( self.host, self.port ) - 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, -} - -- The Helper class used as a primary interface to scripts Helper = { @@ -531,7 +454,7 @@ Helper = { local o = { host = host, port = port, - options = options + options = options or {} } setmetatable(o, self) self.__index = self @@ -542,13 +465,14 @@ Helper = { -- @return status true on success false on failure -- @return err string containing the error message in case status is false connect = function(self) - self.socket = BCSocket:new(self.host, self.port, self.options) - local status, err = self.socket:connect() + self.socket = nmap.new_socket() + self.socket:set_timeout(self.options.timeout or 10000) + local status, err = self.socket:connect(self.host, self.port) if ( not(status) ) then return false, err end - status, self.lhost, self.lport = self.socket.Socket:get_info() + status, self.lhost, self.lport = self.socket:get_info() return status, (status and nil or self.lhost) end, diff --git a/nselib/giop.lua b/nselib/giop.lua index 33bc240da..0dacc2107 100644 --- a/nselib/giop.lua +++ b/nselib/giop.lua @@ -18,15 +18,11 @@ -- -- o Comm -- - Implements a number of functions to handle communication over the --- the Socket class. +-- the socket. -- -- o Helper -- - A helper class that provides easy access to the rest of the library -- --- o Socket --- - This is a copy of the DB2Socket class which provides fundamental --- buffering --- -- -- Example -- ------- @@ -58,6 +54,7 @@ -- local bin = require "bin" +local match = require "match" local nmap = require "nmap" local stdnse = require "stdnse" local string = require "string" @@ -129,7 +126,7 @@ Packet.GIOP = { -- @return status true on success, false on failure -- @return err containing the error message if status is false recv = function( self, socket ) - local status, data = socket:recv( 12 ) + local status, data = socket:receive_buf(match.numbytes(12), true) local pos if ( not(status) ) then return false, "Failed to read Packet.GIOP" end @@ -139,7 +136,7 @@ Packet.GIOP = { pos, self.size = bin.unpack( ( self.byte_order == 0 and ">" or "<") .. "I", data, pos ) - status, data = socket:recv( self.size ) + status, data = socket:receive_buf(match.numbytes(self.size), true) if ( not(status) ) then return false, "Failed to read Packet.GIOP" end self.data = data @@ -420,80 +417,6 @@ Packet.GIOP.list = } --- A socket implementation that provides fundamental buffering and allows for --- reading of an exact number of bytes, instead of atleast ... -Socket = -{ - new = function(self, socket) - local o = {} - setmetatable(o, self) - self.__index = self - o.Socket = socket or nmap.new_socket() - o.Buffer = nil - return o - end, - - getSrcIp = function( self ) - local status, lhost, _, _, _ = self.Socket:get_info() - if (not(status)) then return false, "Error failed to get socket information" end - return true, lhost - end, - - --- Establishes a connection. - -- - -- @param hostid Hostname or IP address. - -- @param port Port number. - -- @param protocol "tcp", "udp", or - -- @return Status (true or false). - -- @return Error code (if status is false). - connect = function( self, hostid, port, protocol ) - local status = self.Socket:set_timeout(10000) - 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, -} - -- Static class containing various message decoders MessageDecoder = { @@ -624,7 +547,7 @@ Helper = { self.__index = self o.host = host o.port = port - o.socket = Socket:new() + o.socket = nmap.new_socket() return o end, @@ -674,14 +597,15 @@ Helper = { -- @return true on success, false on failure -- @return err containing error message when status is false Connect = function( self ) + self.socket:set_timeout(10000) local status, data = self.socket:connect( self.host.ip, self.port.number, "tcp" ) if( not(status) ) then return status, data end self.comm = Comm:new( self.socket ) - status, self.lhost = self.socket:getSrcIp() + status, self.lhost = self.socket:get_info() if ( not(status) ) then self.socket:close() - return false, self.lhost + return false, "Error failed to get socket information" end return true diff --git a/nselib/informix.lua b/nselib/informix.lua index 2ea2deeca..b06bba005 100644 --- a/nselib/informix.lua +++ b/nselib/informix.lua @@ -23,15 +23,11 @@ -- -- o Comm -- - Implements a number of functions to handle communication over the --- the Socket class. +-- the socket. -- -- o Helper -- - A helper class that provides easy access to the rest of the library -- --- o Socket --- - This is a copy of the DB2Socket class which provides fundamental --- buffering --- -- In addition the library contains the following tables with decoder functions -- -- o MetaDataDecoders @@ -77,6 +73,7 @@ local bin = require "bin" local nmap = require "nmap" +local match = require "match" local stdnse = require "stdnse" local table = require "table" _ENV = stdnse.module("informix", stdnse.seeall) @@ -132,76 +129,6 @@ Constants = } } --- A socket implementation that provides fundamental buffering and allows for --- reading of an exact number of bytes, instead of atleast ... -Socket = -{ - new = function(self, socket) - local o = {} - setmetatable(o, self) - self.__index = self - o.Socket = socket or nmap.new_socket() - o.Buffer = nil - return o - end, - - - --- Establishes a connection. - -- - -- @param hostid Hostname or IP address. - -- @param port Port number. - -- @param protocol "tcp", "udp", or - -- @return Status (true or false). - -- @return Error code (if status is false). - connect = function( self, hostid, port, protocol ) - -- Some Informix server seem to take a LOT of time to respond?! - local status = self.Socket:set_timeout(20000) - 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, -} - -- The ColMetaData class ColMetaData = { @@ -387,7 +314,7 @@ MessageDecoders = { -- @return errmsg, Informix error message or decoding error message if -- status is false [Constants.Message.SQ_ERR] = function( socket ) - local status, data = socket:recv(8) + local status, data = socket:receive_buf(match.numbytes(8), true) local _, svcerr, oserr, errmsg, str, len, pos if( not(status) ) then return false, "Failed to decode error response" end @@ -395,12 +322,12 @@ MessageDecoders = { pos, svcerr, oserr, _, len = bin.unpack(">ssss", data ) if( len and len > 0 ) then - status, data = socket:recv(len) + status, data = socket:receive_buf(match.numbytes(len), true) if( not(status) ) then return false, "Failed to decode error response" end _, str = bin.unpack("A" .. len, data) end - status, data = socket:recv(2) + status, data = socket:receive_buf(match.numbytes(2), true) errmsg = Constants.ErrorMsg[svcerr] if ( errmsg and str ) then @@ -418,12 +345,12 @@ MessageDecoders = { local status, data local len, _ - status, data = socket:recv(2) + status, data = socket:receive_buf(match.numbytes(2), true) if( not(status) ) then return false, "Failed to decode SQ_PROTOCOLS response" end _, len = bin.unpack(">S", data ) -- read the remaining data - return socket:recv(len + 2) + return socket:receive_buf(match.numbytes(len + 2), true) end, --- Decodes the SQ_EOT message @@ -439,7 +366,7 @@ MessageDecoders = { -- @return status true on success, false on failure -- @return err error message if status is false [Constants.Message.SQ_DONE] = function( socket ) - local status, data = socket:recv(2) + local status, data = socket:receive_buf(match.numbytes(2), true) local _, len, tmp if( not(status) ) then return false, "Failed to decode SQ_DONE response" end _, len = bin.unpack(">S", data ) @@ -447,9 +374,9 @@ MessageDecoders = { -- For some *@#! reason the SQ_DONE packet sometimes contains an -- length exeeding the length of the packet by one. Attempt to -- detect this and fix. - status, data = socket:recv( len ) + status, data = socket:receive_buf(match.numbytes(len), true) _, tmp = bin.unpack(">S", data, len - 2) - return socket:recv( (tmp == 0) and 3 or 4 ) + return socket:receive_buf(match.numbytes((tmp == 0) and 3 or 4), true) end, --- Decodes the metadata for a result set @@ -458,7 +385,7 @@ MessageDecoders = { -- @return status true on success, false on failure -- @return column_meta table containing the metadata [Constants.Message.SQ_DESCRIBE] = function( socket ) - local status, data = socket:recv(14) + local status, data = socket:receive_buf(match.numbytes(14), true) local pos, cols, col_type, col_name, col_len, col_md, stmt_id local coldesc_len, x local column_meta = {} @@ -470,33 +397,33 @@ MessageDecoders = { if ( cols <= 0 ) then -- We can end up here if we executed a CREATE, UPDATE OR INSERT statement local tmp - status, data = socket:recv(2) + status, data = socket:receive_buf(match.numbytes(2), true) if( not(status) ) then return false, "Failed to decode SQ_DESCRIBE response" end pos, tmp = bin.unpack(">S", data) -- This was the result of a CREATE or UPDATE statement if ( tmp == 0x0f ) then - status, data = socket:recv(26) + status, data = socket:receive_buf(match.numbytes(26), true) -- This was the result of a INSERT statement elseif( tmp == 0x5e ) then - status, data = socket:recv(46) + status, data = socket:receive_buf(match.numbytes(46), true) end return true end - status, data = socket:recv(6) + status, data = socket:receive_buf(match.numbytes(6), true) if( not(status) ) then return false, "Failed to decode SQ_DESCRIBE response" end for i=1, cols do - status, data = socket:recv(2) + status, data = socket:receive_buf(match.numbytes(2), true) if( not(status) ) then return false, "Failed to decode SQ_DESCRIBE response" end pos, col_type = bin.unpack("C", data, 2) if ( MetaDataDecoders[col_type] ) then - status, data = socket:recv(20) + status, data = socket:receive_buf(match.numbytes(20), true) if( not(status) ) then return false, "Failed to read column meta data" end @@ -510,7 +437,7 @@ MessageDecoders = { end if ( iS", data) if( data == Constants.Message.SQ_DONE ) then - status, data = socket:recv(26) + status, data = socket:receive_buf(match.numbytes(26), true) else - status, data = socket:recv(10) + status, data = socket:receive_buf(match.numbytes(10), true) end return true, { metadata = column_meta, stmt_id = stmt_id } end, @@ -561,11 +488,11 @@ MessageDecoders = { while (true) do local pos = 1 - status, data = socket:recv(6) + status, data = socket:receive_buf(match.numbytes(6), true) if( not(status) ) then return false, "Failed to read column data" end local _, total_len = bin.unpack(">I", data, 3) - status, data = socket:recv( ( total_len % 2 == 0 ) and total_len or total_len + 1) + status, data = socket:receive_buf(match.numbytes(( total_len % 2 == 0 ) and total_len or total_len + 1), true) if( not(status) ) then return false, "Failed to read column data" end row = {} @@ -581,7 +508,7 @@ MessageDecoders = { table.insert( row, val ) end - status, data = socket:recv(2) + status, data = socket:receive_buf(match.numbytes(2), true) local _, flags = bin.unpack(">S", data) @@ -598,7 +525,7 @@ MessageDecoders = { local status, tmp = socket:send( tostring(Packet.SQ_ID:new( info.id, nil, "continue" ) ) ) local pkt_type - status, tmp = socket:recv( 2 ) + status, tmp = socket:receive_buf(match.numbytes(2), true) pos, pkt_type = bin.unpack(">S", tmp) return MessageDecoders[pkt_type]( socket, info ) @@ -607,12 +534,12 @@ MessageDecoders = { end -- read the remaining data - status, data = socket:recv( 26 ) + status, data = socket:receive_buf(match.numbytes(26), true) if( not(status) ) then return false, "Failed to read column data" end -- signal finnish reading status, data = socket:send( tostring(Packet.SQ_ID:new( info.id, nil, "end" ) ) ) - status, data = socket:recv( 2 ) + status, data = socket:receive_buf(match.numbytes(2), true) return true, info @@ -629,32 +556,32 @@ MessageDecoders = { local databases = {} while( true ) do - status, data = socket:recv(2) + status, data = socket:receive_buf(match.numbytes(2), true) if ( not(status) ) then return false, "Failed to parse SQ_DBLIST response" end pos, len = bin.unpack(">S", data) if ( 0 == len ) then break end - status, data = socket:recv(len) + status, data = socket:receive_buf(match.numbytes(len), true) if ( not(status) ) then return false, "Failed to parse SQ_DBLIST response" end pos, db = bin.unpack("A" .. len, data ) table.insert( databases, db ) if ( len %2 == 1 ) then - socket:recv(1) + socket:receive_buf(match.numbytes(1), true) if ( not(status) ) then return false, "Failed to parse SQ_DBLIST response" end end end -- read SQ_EOT - status, data = socket:recv(2) + status, data = socket:receive_buf(match.numbytes(2), true) return true, databases end, [Constants.Message.SQ_EXIT] = function( socket ) - local status, data = socket:recv(2) + local status, data = socket:receive_buf(match.numbytes(2), true) if ( not(status) ) then return false, "Failed to parse SQ_EXIT response" end return true @@ -1084,12 +1011,12 @@ Packet.Connect = { -- @return status true on success, false on failure -- @return err msg if status is false readResponse = function( self, socket ) - local status, data = socket:recv( 2 ) + local status, data = socket:receive_buf(match.numbytes(2), true) local len, pos, tmp if ( not(status) ) then return false, data end pos, len = bin.unpack(">S", data) - status, data = socket:recv( len - 2 ) + status, data = socket:receive_buf(match.numbytes(len - 2), true) if ( not(status) ) then return false, data end pos = 13 @@ -1218,7 +1145,7 @@ Comm = local status, data = self.socket:send( tostring(packet) ) if ( not(status) ) then return false, data end - status, data = self.socket:recv( 2 ) + status, data = self.socket:receive_buf(match.numbytes(2), true) _, typ = bin.unpack(">S", data) if ( MessageDecoders[typ] ) then @@ -1249,7 +1176,7 @@ Helper = { self.__index = self o.host = host o.port = port - o.socket = Socket:new() + o.socket = nmap.new_socket() o.instance = instance or "nmap_probe" return o end, @@ -1262,6 +1189,8 @@ Helper = { local status, data local conn, packet + -- Some Informix server seem to take a LOT of time to respond?! + self.socket:set_timeout(20000) status, data = self.socket:connect( self.host.ip, self.port.number, "tcp" ) if( not(status) ) then diff --git a/nselib/iscsi.lua b/nselib/iscsi.lua index 420b695f3..2a80d8a16 100644 --- a/nselib/iscsi.lua +++ b/nselib/iscsi.lua @@ -18,8 +18,6 @@ -- * Comm -- ** A class used to send and receive packet between the library and server -- ** The class handles some of the packet "counting" and value updating --- * Socket --- ** A buffered socket class that allows reading of exakt number of bytes -- * KVP -- ** A key/value pair class that holds key value pairs -- * Helper @@ -39,6 +37,7 @@ local bin = require "bin" local bit = require "bit" local ipOps = require "ipOps" +local match = require "match" local nmap = require "nmap" local stdnse = require "stdnse" local openssl = stdnse.silent_require "openssl" @@ -202,7 +201,7 @@ Packet = { -- @return status true on success, false on failure -- @return resp instance of LoginResponse fromSocket = function( s ) - local status, header = s:recv(48) + local status, header = s:receive_buf(match.numbytes(48), true) if ( not(status) ) then return false, "Failed to read header from socket" @@ -218,7 +217,7 @@ Packet = { local pad = ( 4 - ( resp.data_seg_len % 4 ) ) pad = ( pad == 4 ) and 0 or pad - local status, data = s:recv( resp.data_seg_len + pad ) + local status, data = s:receive_buf(match.numbytes(resp.data_seg_len + pad), true) if ( not(status) ) then return false, "Failed to read data from socket" end @@ -308,7 +307,7 @@ Packet = { local textdata = "" repeat - local status, header = s:recv(48) + local status, header = s:receive_buf(match.numbytes(48), true) local pos, _, flags, _, _, len = bin.unpack(">CCCCI", header) local cont = ( bit.band(flags, 0x40) == 0x40 ) @@ -316,7 +315,7 @@ Packet = { resp.data_seg_len = bit.band(len, 0x00ffffff) local data - status, data = s:recv( resp.data_seg_len ) + status, data = s:receive_buf(match.numbytes(resp.data_seg_len), true) textdata = textdata .. data @@ -415,7 +414,7 @@ Packet = { -- err string containing error message fromSocket = function( s ) local resp = Packet.LogoutResponse:new() - local status, header = s:recv(48) + local status, header = s:receive_buf(match.numbytes(48), true) if ( not(status) ) then return status, header end return true, resp end @@ -469,78 +468,6 @@ Comm = { } ---- A buffered socket implementation -Socket = -{ - - --- Creates a new instance of Socket - -- - -- @return instance of Socket - 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 Hostname or IP address. - -- @param port Port number. - -- @param protocol "tcp", "udp", or - -- @return Status (true or false). - -- @return Error code (if status is false). - connect = function( self, hostid, port, protocol ) - self.Socket:set_timeout(10000) - 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, -} - --- Key/Value pairs class KVP = { @@ -623,7 +550,7 @@ Helper = { setmetatable(o, self) self.__index = self o.host, o.port = host, port - o.socket = Socket:new() + o.socket = nmap.new_socket() return o end, @@ -632,6 +559,7 @@ Helper = { -- @return status true on success, false on failure -- @return err string containing error message is status is false connect = function( self ) + self.socket:set_timeout(10000) local status, err = self.socket:connect(self.host, self.port, "tcp") if ( not(status) ) then return false, err end diff --git a/nselib/ncp.lua b/nselib/ncp.lua index 2133b9aec..dc12b4808 100644 --- a/nselib/ncp.lua +++ b/nselib/ncp.lua @@ -25,9 +25,6 @@ -- - Contains the "native" NCP functions sending the actual request to the -- server. -- --- * Socket --- - A buffered socket implementation --- -- * Helper -- - The prefered script interface to the library containing functions -- that wrap functions from the NCP class using more descriptive names @@ -56,6 +53,7 @@ local bin = require "bin" local bit = require "bit" local ipOps = require "ipOps" +local match = require "match" local nmap = require "nmap" local stdnse = require "stdnse" local string = require "string" @@ -622,7 +620,7 @@ Response = { -- @param socket socket connected to server and ready to receive data -- @return Response containing a new Response instance fromSocket = function(socket) - local status, header = socket:recv(16) + local status, header = socket:receive_buf(match.numbytes(16), true) if ( not(status) ) then return false, "Failed to receive data" end local pos, sig, len = bin.unpack(">II", header) @@ -631,7 +629,7 @@ Response = { local data if ( 0 < len - 16 ) then - status, data = socket:recv(len - 16) + status, data = socket:receive_buf(match.numbytes(len - 16), true) if ( not(status) ) then return false, "Failed to receive data" end end return true, Response:new(header, data) @@ -977,7 +975,8 @@ Helper = { --- Connect the socket and creates a NCP connection -- @return true on success false on failure connect = function(self) - self.socket = Socket:new() + self.socket = nmap.new_socket() + self.socket:set_timeout(5000) local status, err = self.socket:connect(self.host, self.port) if ( not(status) ) then return status, err end @@ -1077,76 +1076,6 @@ Helper = { end, } -Socket = -{ - new = function(self) - local o = {} - setmetatable(o, self) - self.__index = self - o.Socket = nmap.new_socket() - o.Buffer = nil - return o - end, - - --- Sets the socket timeout (@see nmap.set_timeout) - -- @param tm number containing the socket timeout in ms - set_timeout = function(self, tm) self.Socket:set_timeout(tm) end, - - --- Establishes a connection. - -- - -- @param hostid Hostname or IP address. - -- @param port Port number. - -- @param protocol "tcp", "udp", or - -- @return Status (true or false). - -- @return Error code (if status is false). - connect = function( self, hostid, port, protocol ) - self.Socket:set_timeout(5000) - 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, -} - --- "static" Utility class containing mostly conversion functions Util = { diff --git a/nselib/nrpc.lua b/nselib/nrpc.lua index badb5d0ec..bfe2f91a0 100644 --- a/nselib/nrpc.lua +++ b/nselib/nrpc.lua @@ -16,11 +16,6 @@ -- o Helper -- - A helper class that provides easy access to the rest of the library -- --- o DominoSocket --- - This is a copy of the DB2Socket class which provides fundamental --- buffering --- --- -- Example -- ------- -- The following sample code illustrates how scripts can use the Helper class @@ -44,6 +39,7 @@ local bin = require "bin" +local match = require "match" local nmap = require "nmap" local stdnse = require "stdnse" _ENV = stdnse.module("nrpc", stdnse.seeall) @@ -63,16 +59,16 @@ DominoPacket = { return o end, - --- Reads a packet from the DominoSocket + --- Reads a packet from the socket -- - -- @param domsock DominoSocket connected to the server + -- @param domsock socket connected to the server -- @return Status (true or false). -- @return Error code (if status is false). read = function( self, domsock ) - local status, data = domsock:recv(2) + local status, data = domsock:receive_buf(match.numbytes(2), true) local pos, len = bin.unpack( ""tcp", "udp", or - -- @return Status (true or false). - -- @return Error code (if status is false). - connect = function( self, hostid, port, protocol ) - self.Socket:set_timeout(5000) - 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, -} - Helper = { --- Creates a new Helper instance @@ -161,7 +90,7 @@ Helper = { self.__index = self o.host = host o.port = port - o.domsock = DominoSocket:new() + o.domsock = nmap.new_socket() return o end, @@ -170,6 +99,7 @@ Helper = { -- @return status true on success, false on failure -- @return err error message if status is false connect = function( self ) + self.domsock:set_timeout(5000) if( not( self.domsock:connect( self.host.ip, self.port.number, "tcp" ) ) ) then return false, ("ERROR: Failed to connect to Domino server %s:%d\n"):format(self.host, self.port) end diff --git a/nselib/socks.lua b/nselib/socks.lua index 6daca7a3a..a57b99add 100644 --- a/nselib/socks.lua +++ b/nselib/socks.lua @@ -5,6 +5,7 @@ -- local bin = require "bin" +local match = require "match" local nmap = require "nmap" local stdnse = require "stdnse" local string = require "string" @@ -164,82 +165,6 @@ Response = { } --- A buffered socket implementation -Socket = -{ - retries = 3, - - -- Creates a new socket instance - -- @param host table containing the host table - -- @param port table containing the port table - -- @param options table containing options, currenlty supports: - -- timeout - socket timeout in ms - -- @return o new instance of Socket - new = function(self, host, port, options) - local o = { - host = host, - port = port, - options = options or {} - } - setmetatable(o, self) - self.__index = self - o.Socket = nmap.new_socket() - o.Buffer = nil - return o - end, - - -- Connects the socket to the server - -- @return status true on success false on failure - -- @return err string containing error message on failure - connect = function( self ) - self.Socket:set_timeout(self.options.timeout or 10000) - return self.Socket:connect( self.host, self.port ) - 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, -} - - -- The main script interface Helper = { @@ -250,6 +175,7 @@ Helper = { -- timeout - socket timeout in ms -- @return o instance of Helper new = function(self, host, port, options) + options = options or {} local o = { host = host, port = port, options = options } setmetatable(o, self) self.__index = self @@ -273,8 +199,9 @@ Helper = { -- @return status true on success, false on failure -- @return response table containing the respons or err string on failure connect = function(self, auth_method) - self.socket = Socket:new(self.host, self.port, self.options) - local status, err = self.socket:connect() + self.socket = nmap.new_socket() + self.socket:set_timeout(self.options.timeout or 10000) + local status, err = self.socket:connect(self.host, self.port) if ( not(status) ) then return status, err end @@ -286,7 +213,7 @@ Helper = { return false, "Failed to send connection request to server" end - local status, data = self.socket:recv(2) + local status, data = self.socket:receive_buf(match.numbytes(2), true) if ( not(status) ) then self.socket:close() return false, "Failed to receive connection response from server" @@ -332,7 +259,7 @@ Helper = { end if ( 2 == self.auth_method ) then - local status, data = self.socket:recv(2) + local status, data = self.socket:receive_buf(match.numbytes(2), true) local auth = Response.Authenticate:new(data) if ( not(auth) ) then