1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-17 13:09:02 +00:00

o [NSE] Fixed authentication problems in the TNS library that would prevent

authentication from working against Oracle 11.2.0.2.0 XE [Chris Woodbury]
This commit is contained in:
patrik
2011-08-27 08:05:10 +00:00
parent dfe031dbcb
commit a52d443841
2 changed files with 166 additions and 71 deletions

View File

@@ -1,5 +1,8 @@
# Nmap Changelog ($Id$); -*-text-*- # Nmap Changelog ($Id$); -*-text-*-
o [NSE] Fixed authentication problems in the TNS library that would prevent
authentication from working against Oracle 11.2.0.2.0 XE [Chris Woodbury]
o Removed some restrictions on probe matching that, for example, o Removed some restrictions on probe matching that, for example,
prevented a RST/ACK reply from being recognized in a NULL scan. This prevented a RST/ACK reply from being recognized in a NULL scan. This
was found and fixed by Matthew Stickney and Joe McEachern. was found and fixed by Matthew Stickney and Joe McEachern.

View File

@@ -77,7 +77,7 @@
-- @args tns.sid specifies the Oracle instance to connect to -- @args tns.sid specifies the Oracle instance to connect to
-- --
-- Version 0.6 -- Version 0.7
-- Created 07/12/2010 - v0.1 - created by Patrik Karlsson <patrik@cqure.net> -- Created 07/12/2010 - v0.1 - created by Patrik Karlsson <patrik@cqure.net>
-- Revised 07/21/2010 - v0.2 - made minor changes to support 11gR2 on Windows -- Revised 07/21/2010 - v0.2 - made minor changes to support 11gR2 on Windows
-- Revised 07/23/2010 - v0.3 - corrected incorrect example code in docs -- Revised 07/23/2010 - v0.3 - corrected incorrect example code in docs
@@ -91,19 +91,23 @@
-- - added some more documentation and fixed some -- - added some more documentation and fixed some
-- indentation bugs -- indentation bugs
-- <patrik@cqure.net> -- <patrik@cqure.net>
-- Revised 26/08/2011 - v0.7 - applied patch from Chris Woodbury
-- - <patrik@cqure.net>
-- --
-- The following versions have been tested and are known to work: -- The following versions have been tested and are known to work:
-- +--------+---------------+-------+-------------------------------+ -- +--------+---------------+---------+-------+-------------------------------+
-- | OS | DB Version | Arch | Functionality | -- | OS | DB Version | Edition | Arch | Functionality |
-- +--------+---------------+-------+-------------------------------| -- +--------+---------------+---------+-------+-------------------------------|
-- | Win | 11.2.0.2.0 | 64bit | Authentication | -- | Win | 10.2.0.1.0 | EE | 32bit | Authentication |
-- | Win | 11.2.0.1.0 | 64bit | Authentication | -- | Linux | 10.2.0.1.0 | EE | 32bit | Authentication |
-- | Win | 11.1.0.6.0 | 64bit | Authentication | -- | Win | 11.1.0.6.0 | EE | 64bit | Authentication |
-- | Win | 11.1.0.6.0 | 32bit | Authentication, Queries | -- | Win | 11.1.0.6.0 | EE | 32bit | Authentication, Queries |
-- | Win | 11.2.0.1.0 | 32bit | Authentication, Queries | -- | Win | 11.2.0.1.0 | EE | 64bit | Authentication |
-- | Linux | 10.2.0.1.0 | 32bit | Authentication | -- | Win | 11.2.0.1.0 | XE | 32bit | Authentication, Queries |
-- | Linux | 11.2.0.1.0 | 64bit | Authentication | -- | Win | 11.2.0.2.0 | EE | 64bit | Authentication |
-- +--------+---------------+-------+-------------------------------+ -- | Win | 11.2.0.2.0 | XE | 32bit | Authentication, Queries |
-- | Linux | 11.2.0.1.0 | EE | 64bit | Authentication |
-- +--------+---------------+---------+-------+-------------------------------+
-- --
require 'bin' require 'bin'
@@ -453,15 +457,6 @@ Packet.PreAuth = {
return o return o
end, end,
--- Converts a parameter to a string representation
--
-- @param name string containing the parameter name
-- @param value string containing the parameter value
-- @return string containing the parameter key and value
paramToString = function( self, param_name, param_value )
return bin.pack(">CIACIAI", #param_name, #param_name, param_name, #param_value, #param_value, param_value, 0 )
end,
--- Converts the DATA packet to string --- Converts the DATA packet to string
-- --
-- @return string containing the packet -- @return string containing the packet
@@ -479,9 +474,10 @@ Packet.PreAuth = {
data = data .. bin.pack("CA", #self.auth_user, self.auth_user ) data = data .. bin.pack("CA", #self.auth_user, self.auth_user )
for _, v in ipairs( Packet.PreAuth.param_order ) do for _, v in ipairs( Packet.PreAuth.param_order ) do
for k, v2 in pairs(v) do for k, v2 in pairs(v) do
data = data .. self:paramToString( k, self.auth_options[v2] ) data = data .. Marshaller.marshalKvp( k, self.auth_options[v2] )
end end
end end
return data return data
end, end,
@@ -492,26 +488,22 @@ Packet.PreAuth = {
-- @return table containing the keys and values returned by the server -- @return table containing the keys and values returned by the server
parseResponse = function( self, tns ) parseResponse = function( self, tns )
local len, len2, key, val, _ local kvp_count, key, val, kvp_flags
local pos = 6
local kvps = {} local kvps = {}
while( true ) do local pos = 4
pos, len, len2 = bin.unpack("<IC", tns.data, pos ) pos, kvp_count = bin.unpack( "C", tns.data, pos )
if ( len ~= len2 ) then break end pos = 6
pos, key = bin.unpack("A" .. len, tns.data, pos )
pos, len, _ = bin.unpack("<IC", tns.data, pos )
pos, val = bin.unpack("A" .. len, tns.data, pos)
pos = pos + 4
for kvp_itr=1, kvp_count do
pos, key, val, kvp_flags = Marshaller.unmarshalKvp( tns.data, pos )
-- we don't actually do anything with the flags currently, but they're there
kvps[key] = val kvps[key] = val
end end
return true, kvps return true, kvps
end, end,
} }
-- Packet containing authentication data -- Packet containing authentication data
@@ -553,19 +545,6 @@ Packet.Auth = {
return o return o
end, end,
--- Converts a parameter to a string representation
--
-- @param name string containing the parameter name
-- @param value string containing the parameter value
-- @return string containing the parameter key and value
paramToString = function( self, param_name, param_value )
if ( not( param_value ) or #param_value == 0 ) then
return bin.pack(">CIAII", #param_name, #param_name, param_name, #param_value, 0 )
else
return bin.pack(">CIACIAI", #param_name, #param_name, param_name, #param_value, #param_value, param_value, 0 )
end
end,
--- Converts the DATA packet to string --- Converts the DATA packet to string
-- --
-- @return string containing the packet -- @return string containing the packet
@@ -586,11 +565,11 @@ Packet.Auth = {
for k, v in ipairs( self.param_order ) do for k, v in ipairs( self.param_order ) do
if ( v['def'] ) then if ( v['def'] ) then
data = data .. self:paramToString( v['key'], v['def']) data = data .. Marshaller.marshalKvp( v['key'], v['def'] )
elseif ( self.auth_options[ v['var'] ] ) then elseif ( self.auth_options[ v['var'] ] ) then
data = data .. self:paramToString( v['key'], self.auth_options[ v['var'] ] ) data = data .. Marshaller.marshalKvp( v['key'], self.auth_options[ v['var'] ] )
elseif ( self[ v['var'] ] ) then elseif ( self[ v['var'] ] ) then
data = data .. self:paramToString( v['key'], self[ v['var'] ] ) data = data .. Marshaller.marshalKvp( v['key'], self[ v['var'] ] )
end end
end end
return data return data
@@ -601,27 +580,20 @@ Packet.Auth = {
-- @param tns Packet.TNS containing the TNS packet recieved from the server -- @param tns Packet.TNS containing the TNS packet recieved from the server
-- @return table containing the key pair values from the Auth packet -- @return table containing the key pair values from the Auth packet
parseResponse = function( self, tns ) parseResponse = function( self, tns )
local pos = 6 local kvp_count, key, val, kvp_flags
local len, name, val, _ local kvps = {}
local data = tns.data
local response
repeat local pos = 4
pos, len, _ = bin.unpack("CI", data, pos) pos, kvp_count = bin.unpack( "C", tns.data, pos )
if ( len == 0 ) then break end pos = 6
pos, name = bin.unpack("A" .. len, data, pos)
pos, len, _ = bin.unpack("CI", data, pos)
if ( len > 0 ) then
pos, val = bin.unpack("A" .. len, data, pos)
pos = pos + 4
else
pos = pos + 3
end
response = response or {}
response[name] = val
until( name == "AUTH_SVR_RESPONSE" )
return true, response for kvp_itr=1, kvp_count do
pos, key, val, kvp_flags = Marshaller.unmarshalKvp( tns.data, pos )
-- we don't actually do anything with the flags currently, but they're there
kvps[key] = val
end
return true, kvps
end, end,
} }
@@ -1201,6 +1173,126 @@ Packet.QueryResponseAck = {
} }
Marshaller = {
--- Marshals a TNS key-value pair data structure
--
-- @param key The key
-- @param value The value
-- @param flags The flags
-- @return A binary packed string representing the KVP structure
marshalKvp = function( key, value, flags )
flags = flags or 0
local result = ""
result = result .. Marshaller.marshalKvpComponent( key )
result = result .. Marshaller.marshalKvpComponent( value )
result = result .. bin.pack( "<I", flags )
return result
end,
--- Parses a TNS key-value pair data structure.
--
-- @param data Packed string to parse
-- @param pos Position in the string at which the KVP begins
-- @return table containing the last position read, the key, the value, and the KVP flags
unmarshalKvp = function( data, pos )
local key, value, flags
pos, key = Marshaller.unmarshalKvpComponent( data, pos )
pos, value = Marshaller.unmarshalKvpComponent( data, pos )
pos, flags = bin.unpack("<I", data, pos )
return pos, key, value, flags
end,
--- Marshals a key or value element from a TNS key-value pair data structure
--
-- @param value The key or value
-- @return A binary packed string representing the element
marshalKvpComponent = function( value )
local result = ""
value = value or ""
result = result .. bin.pack( "<I", #value )
if ( #value > 0 ) then
-- 64 bytes seems to be the maximum length before Oracle starts
-- chunking strings
local MAX_CHUNK_LENGTH = 64
local split_into_chunks = ( #value > MAX_CHUNK_LENGTH )
if ( not( split_into_chunks ) ) then
-- It's pretty easy if we don't have to split up the string
result = result .. bin.pack( "p", value )
else
-- Otherwise, it's a bit more involved:
-- First, write the multiple-chunk indicator
result = result .. bin.pack( "C", 0xFE )
-- Loop through the string, chunk by chunk
while ( #value > 0 ) do
-- Figure out how much we're writing in this chunk, the
-- remainder of the string, or the maximum, whichever is less
local write_length = MAX_CHUNK_LENGTH
if (#value < MAX_CHUNK_LENGTH) then
write_length = #value
end
-- get a substring of what we're going to write...
local write_value = value:sub( 1, write_length )
-- ...and remove that piece from the remaining string
value = value:sub( write_length + 1 )
result = result .. bin.pack( "p", write_value )
end
-- put a null byte at the end
result = result .. bin.pack( "C", 0 )
end
end
return result
end,
--- Parses a key or value element from a TNS key-value pair data structure.
--
-- @param data Packed string to parse
-- @param pos Position in the string at which the element begins
-- @return table containing the last position read and the value parsed
unmarshalKvpComponent = function( data, pos )
local value_len, chunk_len
local value, chunk = "", ""
local has_multiple_chunks = false
-- read the 32-bit total length of the value
pos, value_len = bin.unpack("<I", data, pos )
if ( value_len == 0 ) then
value = ""
else
-- Look at the first byte after the total length. If the value is
-- broken up into multiple chunks, this will be indicated by this
-- byte being 0xFE.
local _, first_byte = bin.unpack("C", data, pos )
if ( first_byte == 0xFE ) then
has_multiple_chunks = true
pos = pos + 1 -- move pos past the multiple-chunks indicator
end
-- Loop through the chunks until we read the whole value
while ( value:len() < value_len ) do
pos, chunk = bin.unpack("p", data, pos )
value = value .. chunk
end
if ( has_multiple_chunks ) then
pos = pos + 1 -- there's a null byte after the last chunk
end
end
return pos, value
end,
}
-- The TNS communication class uses the TNSSocket to transmit data -- The TNS communication class uses the TNSSocket to transmit data
Comm = { Comm = {