Fixes #434. Always use Timeout.timeout() -- on Ruby 1.9 this results in the Timeout::TimeoutError exception vs RuntimeError
git-svn-id: file:///home/svn/framework3/trunk@7323 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
80a262f991
commit
075b8c5fa4
|
@ -20,7 +20,7 @@ def initialize(info = {})
|
|||
[
|
||||
OptInt.new('RUNTIME', [ true, "The number of seconds to run the test", 5 ] )
|
||||
], Auxiliary::Timed)
|
||||
|
||||
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -30,10 +30,11 @@ def run
|
|||
secs = datastore['RUNTIME']
|
||||
print_status("Running module for #{secs} seconds...")
|
||||
begin
|
||||
timeout(secs) { self.run_timed }
|
||||
Timeout.timeout(secs) { self.run_timed }
|
||||
rescue Timeout::Error
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ require 'msf/core/exploit/tcp'
|
|||
module Exploit::Remote::FtpServer
|
||||
|
||||
include Exploit::Remote::TcpServer
|
||||
|
||||
|
||||
#
|
||||
# Creates an instance of an FTP exploit module.
|
||||
#
|
||||
|
@ -24,90 +24,90 @@ module Exploit::Remote::FtpServer
|
|||
OptPort.new('SRVPORT', [ true, "The local port to listen on.", 21 ])
|
||||
], Msf::Exploit::Remote::FtpServer)
|
||||
end
|
||||
|
||||
|
||||
def setup
|
||||
super
|
||||
@state = {}
|
||||
end
|
||||
|
||||
|
||||
def on_client_connect(c)
|
||||
@state[c] = {
|
||||
:name => "#{c.peerhost}:#{c.peerport}",
|
||||
:ip => c.peerhost,
|
||||
:port => c.peerport,
|
||||
:user => nil,
|
||||
:name => "#{c.peerhost}:#{c.peerport}",
|
||||
:ip => c.peerhost,
|
||||
:port => c.peerport,
|
||||
:user => nil,
|
||||
:pass => nil
|
||||
}
|
||||
|
||||
|
||||
active_data_port_for_client(c, 20)
|
||||
|
||||
|
||||
c.put "220 FTP Server Ready\r\n"
|
||||
end
|
||||
|
||||
|
||||
def on_client_data(c)
|
||||
data = c.get_once
|
||||
return if not data
|
||||
|
||||
|
||||
cmd,arg = data.strip.split(/\s+/, 2)
|
||||
arg ||= ""
|
||||
|
||||
|
||||
return if not cmd
|
||||
|
||||
|
||||
# Allow per-command overrides
|
||||
if(self.respond_to?("on_client_command_#{cmd.downcase}"))
|
||||
return self.send("on_client_command_#{cmd.downcase}", c, arg)
|
||||
end
|
||||
|
||||
|
||||
case cmd.upcase
|
||||
when 'USER'
|
||||
@state[c][:user] = arg
|
||||
c.put "331 User name okay, need password...\r\n"
|
||||
return
|
||||
|
||||
|
||||
when 'PASS'
|
||||
@state[c][:pass] = arg
|
||||
print_status("#{@state[c][:name]} LOGIN #{@state[c][:user]} / #{@state[c][:pass]}")
|
||||
c.put "230 Login OK\r\n"
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
when 'QUIT'
|
||||
c.put "221 Logout\r\n"
|
||||
return
|
||||
|
||||
|
||||
when 'SYST'
|
||||
c.put "215 UNIX Type: L8\r\n"
|
||||
return
|
||||
|
||||
|
||||
when 'TYPE'
|
||||
c.put "200 Type is set\r\n"
|
||||
return
|
||||
|
||||
|
||||
when 'CWD'
|
||||
c.put "250 CWD command successful.\r\n"
|
||||
return
|
||||
|
||||
|
||||
when 'PWD'
|
||||
c.put "257 \"/\" is current directory.\r\n"
|
||||
return
|
||||
|
||||
|
||||
when 'SIZE'
|
||||
c.put "213 1\r\n"
|
||||
return
|
||||
|
||||
|
||||
when 'MDTM'
|
||||
c.put "213 #{Time.now.strftime("%Y%m%d%H%M%S")}\r\n"
|
||||
return
|
||||
|
||||
|
||||
when 'PORT'
|
||||
port = arg.split(',')[4,2]
|
||||
if(not port and port.length == 2)
|
||||
c.put("500 Illegal PORT command.\r\n")
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
port = port.map{|x| x.to_i}.pack('C*').unpack('n')[0]
|
||||
active_data_port_for_client(c, port)
|
||||
|
||||
|
||||
c.put "200 PORT command successful.\r\n"
|
||||
return
|
||||
|
||||
|
@ -119,28 +119,28 @@ module Exploit::Remote::FtpServer
|
|||
pasv = (daddr.split('.') + [dport].pack('n').unpack('CC')).join(',')
|
||||
c.put "227 Entering Passive Mode (#{pasv})\r\n"
|
||||
return
|
||||
|
||||
|
||||
when /^(STOR|MKD|REM|DEL|RMD)$/
|
||||
c.put "500 Access Denied\r\n"
|
||||
return
|
||||
|
||||
else
|
||||
print_status("#{@state[c][:name]} UNKNOWN '#{cmd} #{arg}'")
|
||||
print_status("#{@state[c][:name]} UNKNOWN '#{cmd} #{arg}'")
|
||||
c.put("500 '#{cmd} #{arg}': command not understood.\r\n")
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
return
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
def on_client_close(c)
|
||||
@state.delete(c)
|
||||
end
|
||||
|
||||
|
||||
def passive_data_port_for_client(c)
|
||||
@state[c][:mode] = :passive
|
||||
|
||||
|
||||
if(not @state[c][:passive_sock])
|
||||
s = Rex::Socket::TcpServer.create(
|
||||
'LocalHost' => '0.0.0.0',
|
||||
|
@ -153,13 +153,13 @@ module Exploit::Remote::FtpServer
|
|||
@state[c][:passive_sock] = s
|
||||
@state[c][:passive_port] = dport
|
||||
end
|
||||
|
||||
|
||||
@state[c][:passive_port]
|
||||
end
|
||||
|
||||
|
||||
def active_data_port_for_client(c,port)
|
||||
@state[c][:mode] = :active
|
||||
|
||||
|
||||
connector = Proc.new {
|
||||
host = c.peerhost.dup
|
||||
sock = Rex::Socket::Tcp.create(
|
||||
|
@ -171,12 +171,12 @@ module Exploit::Remote::FtpServer
|
|||
|
||||
@state[c][:active_connector] = connector
|
||||
@state[c][:active_port] = port
|
||||
end
|
||||
|
||||
|
||||
def establish_data_connection(c)
|
||||
end
|
||||
|
||||
|
||||
def establish_data_connection(c)
|
||||
begin
|
||||
Timeout.timeout(20) do
|
||||
Timeout.timeout(20) do
|
||||
if(@state[c][:mode] == :active)
|
||||
return @state[c][:active_connector].call()
|
||||
end
|
||||
|
@ -184,13 +184,14 @@ module Exploit::Remote::FtpServer
|
|||
return @state[c][:passive_sock].accept
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
rescue ::Exception => e
|
||||
print_error("Failed to establish data connection: #{e.class} #{e}")
|
||||
end
|
||||
|
||||
nil
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ module Stream
|
|||
def write(buf, opts = {})
|
||||
tsent = 0
|
||||
bidx = 0
|
||||
|
||||
|
||||
begin
|
||||
while (bidx < buf.length)
|
||||
sent = fd.syswrite(buf[bidx, 32768])
|
||||
|
@ -112,14 +112,14 @@ module Stream
|
|||
def >>
|
||||
get_once
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# This method writes to the stream, optionally timing out after a period of
|
||||
# time.
|
||||
#
|
||||
def timed_write(buf, wait = def_write_timeout, opts = {})
|
||||
if (wait and wait > 0)
|
||||
timeout(wait) {
|
||||
Timeout.timeout(wait) {
|
||||
return write(buf, opts)
|
||||
}
|
||||
else
|
||||
|
@ -133,7 +133,7 @@ module Stream
|
|||
#
|
||||
def timed_read(length = nil, wait = def_read_timeout, opts = {})
|
||||
if (wait and wait > 0)
|
||||
timeout(wait) {
|
||||
Timeout.timeout(wait) {
|
||||
return read(length, opts)
|
||||
}
|
||||
else
|
||||
|
@ -167,7 +167,7 @@ module Stream
|
|||
end
|
||||
|
||||
|
||||
#
|
||||
#
|
||||
# This method emulates the behavior of Pex::Socket::Recv in MSF2
|
||||
#
|
||||
def get_once(length = -1, timeout = def_read_timeout)
|
||||
|
@ -175,14 +175,14 @@ module Stream
|
|||
if (has_read_data?(timeout) == false)
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
bsize = (length == -1) ? def_block_size : length
|
||||
|
||||
begin
|
||||
return read(bsize)
|
||||
rescue Exception
|
||||
end
|
||||
|
||||
|
||||
return ''
|
||||
end
|
||||
|
||||
|
@ -213,7 +213,7 @@ module Stream
|
|||
rescue EOFError
|
||||
eof = true
|
||||
end
|
||||
|
||||
|
||||
# If we read zero bytes and we had data, then we've hit EOF
|
||||
if (temp and temp.length == 0)
|
||||
eof = true
|
||||
|
@ -235,7 +235,7 @@ module Stream
|
|||
|
||||
buf += temp
|
||||
lps += 1
|
||||
|
||||
|
||||
break if (lps >= def_max_loops)
|
||||
end
|
||||
|
||||
|
@ -296,3 +296,4 @@ protected
|
|||
end
|
||||
|
||||
end end
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'timeout'
|
||||
require 'thread'
|
||||
require 'thread'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
|
@ -32,7 +32,7 @@ class PacketResponseWaiter
|
|||
end
|
||||
|
||||
#
|
||||
# Checks to see if this waiter instance is waiting for the supplied
|
||||
# Checks to see if this waiter instance is waiting for the supplied
|
||||
# packet based on its request identifier.
|
||||
#
|
||||
def waiting_for?(packet)
|
||||
|
@ -57,7 +57,7 @@ class PacketResponseWaiter
|
|||
#
|
||||
def wait(interval)
|
||||
begin
|
||||
timeout(interval) {
|
||||
Timeout.timeout(interval) {
|
||||
while(not self.done)
|
||||
select(nil, nil, nil, 0.1)
|
||||
end
|
||||
|
@ -74,3 +74,4 @@ class PacketResponseWaiter
|
|||
end
|
||||
|
||||
end; end; end
|
||||
|
||||
|
|
|
@ -20,11 +20,11 @@ class Rex::Proto::DCERPC::Client::UnitTest < Test::Unit::TestCase
|
|||
|
||||
def setup_test(read, write, force_mock = false)
|
||||
srand(0)
|
||||
mock_unmake() # always do this, just to be sure. yes, it slows it down. but...
|
||||
mock_unmake() # always do this, just to be sure. yes, it slows it down. but...
|
||||
|
||||
if (force_mock or !$_REX_TEST_NO_MOCK)
|
||||
mock_make(read,write)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def mock_make(read, write)
|
||||
|
@ -40,7 +40,7 @@ class Rex::Proto::DCERPC::Client::UnitTest < Test::Unit::TestCase
|
|||
mock.mock_handle(:close) { nil }
|
||||
mock.mock_handle(:read) { read.shift }
|
||||
mock.mock_handle(:get_once) { read.shift }
|
||||
mock.mock_handle(:write) { |data|
|
||||
mock.mock_handle(:write) { |data|
|
||||
expected = write.shift
|
||||
if data != expected
|
||||
write_id = write_size - write.size
|
||||
|
@ -49,7 +49,7 @@ class Rex::Proto::DCERPC::Client::UnitTest < Test::Unit::TestCase
|
|||
end
|
||||
data.length
|
||||
}
|
||||
mock.mock_handle(:put) { |data|
|
||||
mock.mock_handle(:put) { |data|
|
||||
expected = write.shift
|
||||
if data != expected
|
||||
write_id = write_size - write.size
|
||||
|
@ -98,7 +98,7 @@ class Rex::Proto::DCERPC::Client::UnitTest < Test::Unit::TestCase
|
|||
c = Klass.new(handle, socket)
|
||||
assert_instance_of(Rex::Proto::DCERPC::Client, c, 'instance')
|
||||
end
|
||||
|
||||
|
||||
def test_bind_fail
|
||||
write = ["\x05\x00\x0b\x03\x10\x00\x00\x00\x48\x00\x00\x00\x00\x00\x00\x00\xd0\x16\xd0\x16\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x01\x00\xbb\xbb\xaa\xaa\x00\x00\x10\x36\x98\x33\x46\xc3\xf8\x7e\x34\x5a\x02\x00\x00\x00\x04\x5d\x88\x8a\xeb\x1c\xc9\x11\x9f\xe8\x08\x00\x2b\x10\x48\x60\x02\x00\x00\x00"]
|
||||
read = [ "\x05\x00\x0c\x03\x10\x00\x00\x00\x3c\x00\x00\x00\x00\x00\x00\x00\xd0\x16\xd0\x16\x6c\x66\x00\x00\x04\x00\x31\x33\x35\x00\x92\xc0\x01\x00\x00\x00\x02\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"]
|
||||
|
@ -139,10 +139,10 @@ class Rex::Proto::DCERPC::Client::UnitTest < Test::Unit::TestCase
|
|||
"\x05\x00\x03\x23\x10\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x01\x1c\x00\x00\x00\x00"
|
||||
]
|
||||
setup_test(read, write)
|
||||
|
||||
|
||||
socket = Rex::Socket.create_tcp('PeerHost' => $_REX_TEST_SMB_HOST, 'PeerPort' => 135)
|
||||
handle = Rex::Proto::DCERPC::Handle.new(['E1AF8308-5D1F-11C9-91A4-08002B14A0FA', '3.0'], 'ncacn_ip_tcp', $_REX_TEST_SMB_HOST, [135])
|
||||
|
||||
|
||||
c = Klass.new(handle, socket)
|
||||
assert_instance_of(Rex::Proto::DCERPC::Client, c, 'instance')
|
||||
assert_raise(Rex::Proto::DCERPC::Exceptions::Fault) {
|
||||
|
@ -155,10 +155,10 @@ class Rex::Proto::DCERPC::Client::UnitTest < Test::Unit::TestCase
|
|||
def test_segmented_read_writes
|
||||
bind_expected = "\005\000\v\003\020\000\000\000H\000\000\000\000\000\000\000\320\026\320\026\000\000\000\000\001\000\000\000\000\000\001\000\230\320\377k\022\241\0206\2303F\303\370~4Z\001\000\000\000\004]\210\212\353\034\311\021\237\350\010\000+\020H`\002\000\000\000"
|
||||
bind_response = "\x05\x00\x0C\x03\x10\x00\x00\x00\x44\x00\x00\x00\x00\x00\x00\x00\xB8\x10\xB8\x10\xB2\x73\x00\x00\x0C\x00\x5C\x50\x49\x50\x45\x5C\x6C\x73\x61\x73\x73\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x04\x5D\x88\x8A\xEB\x1C\xC9\x11\x9F\xE8\x08\x00\x2B\x10\x48\x60\x02\x00\x00\x00"
|
||||
|
||||
|
||||
socket = FlexMock.new
|
||||
#socket.should_ignore_missing()
|
||||
|
||||
|
||||
@write_data = ''
|
||||
|
||||
socket.mock_handle(:write) {
|
||||
|
@ -175,7 +175,7 @@ class Rex::Proto::DCERPC::Client::UnitTest < Test::Unit::TestCase
|
|||
end
|
||||
data = read_data.slice!(0, size)
|
||||
if data.length == 0
|
||||
data = nil
|
||||
data = nil
|
||||
end
|
||||
data
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ class Rex::Proto::DCERPC::Client::UnitTest < Test::Unit::TestCase
|
|||
end
|
||||
data = read_data.slice!(0, size)
|
||||
if data.length == 0
|
||||
data = nil
|
||||
data = nil
|
||||
end
|
||||
data
|
||||
}
|
||||
|
@ -195,7 +195,7 @@ class Rex::Proto::DCERPC::Client::UnitTest < Test::Unit::TestCase
|
|||
c = Klass.new(@handle, socket, 'segment_write' => 1, 'segment_read' => 1)
|
||||
assert_equal(bind_expected, @write_data, 'bind')
|
||||
assert_instance_of(Rex::Proto::DCERPC::Client, c, 'instance')
|
||||
|
||||
|
||||
# XXX - would be nice to test a success, as well as a failure, but
|
||||
# hell... we don't care if the decoder is "right" here, just that it
|
||||
# returns data. Test the decoder in the decoder I say!
|
||||
|
@ -213,8 +213,8 @@ class Rex::Proto::DCERPC::Client::UnitTest < Test::Unit::TestCase
|
|||
|size|
|
||||
data = read_data.slice!(0, size)
|
||||
if data.length == 0
|
||||
data = nil
|
||||
else
|
||||
data = nil
|
||||
else
|
||||
end
|
||||
data
|
||||
}
|
||||
|
@ -249,7 +249,7 @@ class Rex::Proto::DCERPC::Client::UnitTest < Test::Unit::TestCase
|
|||
setup_test(read, write)
|
||||
require 'rex/proto/smb/simpleclient'
|
||||
begin
|
||||
timeout($_REX_TEST_TIMEOUT) {
|
||||
Timeout.timeout($_REX_TEST_TIMEOUT) {
|
||||
s = Rex::Socket.create_tcp( 'PeerHost' => $_REX_TEST_SMB_HOST, 'PeerPort' => 445)
|
||||
|
||||
smb = Rex::Proto::SMB::SimpleClient.new(s, true)
|
||||
|
@ -267,7 +267,7 @@ class Rex::Proto::DCERPC::Client::UnitTest < Test::Unit::TestCase
|
|||
assert_instance_of(Rex::Proto::DCERPC::Handle, handle, 'handle')
|
||||
dcerpc = Rex::Proto::DCERPC::Client.new(handle, f) # , 'segment_read' => 0)
|
||||
assert_instance_of(Rex::Proto::DCERPC::Client, dcerpc, 'bind')
|
||||
s.close
|
||||
s.close
|
||||
}
|
||||
rescue Timeout::Error
|
||||
flunk('timeout')
|
||||
|
@ -285,7 +285,7 @@ class Rex::Proto::DCERPC::Client::UnitTest < Test::Unit::TestCase
|
|||
]
|
||||
setup_test(read, write)
|
||||
begin
|
||||
timeout($_REX_TEST_TIMEOUT) {
|
||||
Timeout.timeout($_REX_TEST_TIMEOUT) {
|
||||
s = Rex::Socket.create_tcp('PeerHost' => $_REX_TEST_SMB_HOST, 'PeerPort' => 135)
|
||||
handle = Rex::Proto::DCERPC::Handle.new(['E1AF8308-5D1F-11C9-91A4-08002B14A0FA', '3.0'], 'ncacn_ip_tcp', $_REX_TEST_SMB_HOST, [135])
|
||||
assert_instance_of(Rex::Proto::DCERPC::Handle, handle, 'handle')
|
||||
|
@ -294,7 +294,7 @@ class Rex::Proto::DCERPC::Client::UnitTest < Test::Unit::TestCase
|
|||
|
||||
stub = "\x00" * (4 * 9) + "\x01\x00\x00\x00"
|
||||
got = dcerpc.call(0x02, stub)
|
||||
s.close
|
||||
s.close
|
||||
}
|
||||
rescue Timeout::Error
|
||||
flunk('timeout')
|
||||
|
@ -312,7 +312,7 @@ class Rex::Proto::DCERPC::Client::UnitTest < Test::Unit::TestCase
|
|||
]
|
||||
setup_test(read, write)
|
||||
begin
|
||||
timeout($_REX_TEST_TIMEOUT) {
|
||||
Timeout.timeout($_REX_TEST_TIMEOUT) {
|
||||
s = Rex::Socket.create_tcp('PeerHost' => $_REX_TEST_SMB_HOST, 'PeerPort' => 135)
|
||||
handle = Rex::Proto::DCERPC::Handle.new(['E1AF8308-5D1F-11C9-91A4-08002B14A0FA', '3.0'], 'ncacn_ip_tcp', $_REX_TEST_SMB_HOST, [135])
|
||||
assert_instance_of(Rex::Proto::DCERPC::Handle, handle, 'handle')
|
||||
|
@ -321,7 +321,7 @@ class Rex::Proto::DCERPC::Client::UnitTest < Test::Unit::TestCase
|
|||
|
||||
stub = "\x00" * (4 * 9) + "\x01\x00\x00\x00"
|
||||
got = dcerpc.call(0x02, stub)
|
||||
s.close
|
||||
s.close
|
||||
}
|
||||
rescue Timeout::Error
|
||||
flunk('timeout')
|
||||
|
@ -338,7 +338,7 @@ class Rex::Proto::DCERPC::Client::UnitTest < Test::Unit::TestCase
|
|||
]
|
||||
setup_test(read, write)
|
||||
begin
|
||||
timeout($_REX_TEST_TIMEOUT) {
|
||||
Timeout.timeout($_REX_TEST_TIMEOUT) {
|
||||
s = Rex::Socket.create_tcp('PeerHost' => $_REX_TEST_SMB_HOST, 'PeerPort' => 135)
|
||||
handle = Rex::Proto::DCERPC::Handle.new(['E1AF8308-5D1F-11C9-91A4-08002B14A0FA', '3.0'], 'ncacn_ip_tcp', $_REX_TEST_SMB_HOST, [135])
|
||||
assert_instance_of(Rex::Proto::DCERPC::Handle, handle, 'handle')
|
||||
|
@ -347,7 +347,7 @@ class Rex::Proto::DCERPC::Client::UnitTest < Test::Unit::TestCase
|
|||
|
||||
stub = "\x00" * (4 * 9) + "\x01\x00\x00\x00"
|
||||
got = dcerpc.call(0x02, stub)
|
||||
s.close
|
||||
s.close
|
||||
}
|
||||
rescue Timeout::Error
|
||||
flunk('timeout')
|
||||
|
@ -363,7 +363,7 @@ class Rex::Proto::DCERPC::Client::UnitTest < Test::Unit::TestCase
|
|||
write = ["\005\000\v\003\020\000\000\000H\000\000\000\000\000\000\000\320\026\320\026\000\000\000\000\001\000\000\000\000\000\001\000\010\203\257\341\037]\311\021\221\244\010\000+\024\240\372\003\000\000\000\004]\210\212\353\034\311\021\237\350\010\000+\020H`\002\000\000\000"]
|
||||
setup_test(read, write)
|
||||
begin
|
||||
timeout($_REX_TEST_TIMEOUT) {
|
||||
Timeout.timeout($_REX_TEST_TIMEOUT) {
|
||||
handle = Rex::Proto::DCERPC::Handle.new(['E1AF8308-5D1F-11C9-91A4-08002B14A0FA', '3.0'], 'ncacn_ip_tcp', $_REX_TEST_SMB_HOST, [135])
|
||||
assert_instance_of(Rex::Proto::DCERPC::Handle, handle, 'handle')
|
||||
dcerpc = Rex::Proto::DCERPC::Client.new(handle, nil)
|
||||
|
@ -373,7 +373,7 @@ class Rex::Proto::DCERPC::Client::UnitTest < Test::Unit::TestCase
|
|||
flunk('timeout')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def test_setup_socket_ncacn_np_socket
|
||||
read = ["\x82\x00\x00\x00",
|
||||
"\x00\x00\x00\x55\xff\x53\x4d\x42\x72\x00\x00\x00\x00\x98\x01\x28\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x2f\xaa\x00\x00\xac\x0a\x11\x03\x00\x03\x0a\x00\x01\x00\x04\x11\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\xfd\xe3\x00\x80\xca\x3d\x91\x3c\x0b\xfd\xc5\x01\xe0\x01\x00\x10\x00\x8b\x3c\x73\xd2\x53\x9e\x28\x48\xa2\xac\x68\xae\xd1\x2e\x41\x5a",
|
||||
|
@ -402,8 +402,8 @@ class Rex::Proto::DCERPC::Client::UnitTest < Test::Unit::TestCase
|
|||
]
|
||||
setup_test(read, write)
|
||||
begin
|
||||
timeout($_REX_TEST_TIMEOUT) {
|
||||
s = Rex::Socket.create_tcp('PeerHost' => $_REX_TEST_SMB_HOST, 'PeerPort' => 139)
|
||||
Timeout.timeout($_REX_TEST_TIMEOUT) {
|
||||
s = Rex::Socket.create_tcp('PeerHost' => $_REX_TEST_SMB_HOST, 'PeerPort' => 139)
|
||||
|
||||
handle = Rex::Proto::DCERPC::Handle.new(['4b324fc8-1670-01d3-1278-5a47bf6ee188', '3.0'], 'ncacn_np', $_REX_TEST_SMB_HOST, ['\BROWSER'])
|
||||
assert_instance_of(Rex::Proto::DCERPC::Handle, handle, 'handle')
|
||||
|
@ -449,16 +449,16 @@ read = [
|
|||
]
|
||||
setup_test(read, write)
|
||||
|
||||
timeout($_REX_TEST_TIMEOUT) {
|
||||
Timeout.timeout($_REX_TEST_TIMEOUT) {
|
||||
handle = Rex::Proto::DCERPC::Handle.new(['4b324fc8-1670-01d3-1278-5a47bf6ee188', '3.0'], 'ncacn_np', $_REX_TEST_SMB_HOST, ['\BROWSER'])
|
||||
dcerpc = Rex::Proto::DCERPC::Client.new(handle, nil)
|
||||
assert_instance_of(Rex::Proto::DCERPC::Client, dcerpc, 'bind')
|
||||
|
||||
require 'rex/proto/dcerpc/ndr'
|
||||
stub =
|
||||
stub =
|
||||
Rex::Proto::DCERPC::NDR.long(1) +
|
||||
Rex::Proto::DCERPC::NDR.UnicodeConformantVaryingString('AAAA') +
|
||||
|
||||
|
||||
# Type 33
|
||||
Rex::Proto::DCERPC::NDR.long(1) +
|
||||
Rex::Proto::DCERPC::NDR.short(2) +
|
||||
|
@ -487,4 +487,5 @@ read = [
|
|||
end
|
||||
|
||||
rescue LoadError
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -56,10 +56,10 @@ class Client
|
|||
'pad_post_params_count' => 8, # integer
|
||||
'uri_fake_end' => false, # bool
|
||||
'uri_fake_params_start' => false, # bool
|
||||
'header_folding' => false, # bool
|
||||
'header_folding' => false, # bool
|
||||
'chunked_size' => 0 # integer
|
||||
}
|
||||
|
||||
|
||||
# This is not used right now...
|
||||
self.config_types = {
|
||||
'uri_encode_mode' => ['hex-normal', 'hex-all', 'hex-random', 'u-normal', 'u-random', 'u-all'],
|
||||
|
@ -90,7 +90,7 @@ class Client
|
|||
'chunked_size' => 'integer'
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Set configuration options
|
||||
#
|
||||
|
@ -99,7 +99,7 @@ class Client
|
|||
self.config[var]=val
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Create an arbitrary HTTP request
|
||||
#
|
||||
|
@ -108,30 +108,30 @@ class Client
|
|||
c_uri = opts['uri'] || '/'
|
||||
c_body = opts['data'] || ''
|
||||
c_meth = opts['method'] || 'GET'
|
||||
c_prot = opts['proto'] || 'HTTP'
|
||||
c_prot = opts['proto'] || 'HTTP'
|
||||
c_vers = opts['version'] || config['version'] || '1.1'
|
||||
c_qs = opts['query']
|
||||
c_ag = opts['agent'] || config['agent']
|
||||
c_cook = opts['cookie'] || config['cookie']
|
||||
c_host = opts['vhost'] || config['vhost']
|
||||
c_head = opts['headers'] || config['headers'] || {}
|
||||
c_rawh = opts['raw_headers']|| config['raw_headers'] || ''
|
||||
c_conn = opts['connection']
|
||||
c_rawh = opts['raw_headers']|| config['raw_headers'] || ''
|
||||
c_conn = opts['connection']
|
||||
c_auth = opts['basic_auth'] || config['basic_auth'] || ''
|
||||
|
||||
|
||||
uri = set_uri(c_uri)
|
||||
|
||||
|
||||
req = ''
|
||||
req << set_method(c_meth)
|
||||
req << set_method_uri_spacer()
|
||||
req << set_uri_prepend()
|
||||
req << (c_enc ? set_encode_uri(uri) : uri)
|
||||
|
||||
|
||||
if (c_qs)
|
||||
req << '?'
|
||||
req << (c_enc ? set_encode_qs(c_qs) : c_qs)
|
||||
end
|
||||
|
||||
|
||||
req << set_uri_append()
|
||||
req << set_uri_version_spacer()
|
||||
req << set_version(c_prot, c_vers)
|
||||
|
@ -141,17 +141,17 @@ class Client
|
|||
if (c_auth.length > 0)
|
||||
req << set_basic_auth_header(c_auth)
|
||||
end
|
||||
|
||||
|
||||
req << set_cookie_header(c_cook)
|
||||
req << set_connection_header(c_conn)
|
||||
req << set_extra_headers(c_head)
|
||||
req << set_raw_headers(c_rawh)
|
||||
req << set_raw_headers(c_rawh)
|
||||
req << set_body(c_body)
|
||||
|
||||
|
||||
req
|
||||
end
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Create a CGI compatible request
|
||||
#
|
||||
|
@ -178,16 +178,16 @@ class Client
|
|||
uri = set_cgi(c_cgi)
|
||||
qstr = c_qs
|
||||
pstr = c_body
|
||||
|
||||
|
||||
if (config['pad_get_params'])
|
||||
1.upto(config['pad_get_params_count'].to_i) do |i|
|
||||
qstr << '&' if qstr.length > 0
|
||||
qstr << set_encode_uri(Rex::Text.rand_text_alphanumeric(rand(32)+1))
|
||||
qstr << '='
|
||||
qstr << set_encode_uri(Rex::Text.rand_text_alphanumeric(rand(32)+1))
|
||||
qstr << set_encode_uri(Rex::Text.rand_text_alphanumeric(rand(32)+1))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
c_varg.each_pair do |var,val|
|
||||
qstr << '&' if qstr.length > 0
|
||||
qstr << set_encode_uri(var)
|
||||
|
@ -200,10 +200,10 @@ class Client
|
|||
pstr << '&' if qstr.length > 0
|
||||
pstr << set_encode_uri(Rex::Text.rand_text_alphanumeric(rand(32)+1))
|
||||
pstr << '='
|
||||
pstr << set_encode_uri(Rex::Text.rand_text_alphanumeric(rand(32)+1))
|
||||
pstr << set_encode_uri(Rex::Text.rand_text_alphanumeric(rand(32)+1))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
c_varp.each_pair do |var,val|
|
||||
pstr << '&' if pstr.length > 0
|
||||
pstr << set_encode_uri(var)
|
||||
|
@ -221,7 +221,7 @@ class Client
|
|||
req << '?'
|
||||
req << qstr
|
||||
end
|
||||
|
||||
|
||||
req << set_path_info(c_path)
|
||||
req << set_uri_append()
|
||||
req << set_uri_version_spacer()
|
||||
|
@ -232,19 +232,19 @@ class Client
|
|||
if (c_auth.length > 0)
|
||||
req << set_basic_auth_header(c_auth)
|
||||
end
|
||||
|
||||
|
||||
req << set_cookie_header(c_cook)
|
||||
req << set_connection_header(c_conn)
|
||||
req << set_connection_header(c_conn)
|
||||
req << set_extra_headers(c_head)
|
||||
|
||||
|
||||
req << set_content_type_header(c_type)
|
||||
req << set_content_len_header(pstr.length)
|
||||
req << set_chunked_header()
|
||||
req << set_raw_headers(c_rawh)
|
||||
req << set_body(pstr)
|
||||
|
||||
req
|
||||
end
|
||||
req
|
||||
end
|
||||
|
||||
#
|
||||
# Connects to the remote server if possible.
|
||||
|
@ -277,7 +277,7 @@ class Client
|
|||
def close
|
||||
if (self.conn)
|
||||
self.conn.shutdown
|
||||
self.conn.close
|
||||
self.conn.close
|
||||
end
|
||||
|
||||
self.conn = nil
|
||||
|
@ -295,7 +295,7 @@ class Client
|
|||
# Send a HTTP request to the server
|
||||
# TODO:
|
||||
# * Handle junk pipeline requests
|
||||
def send_request(req)
|
||||
def send_request(req)
|
||||
# Connect to the server
|
||||
connect
|
||||
|
||||
|
@ -307,7 +307,7 @@ class Client
|
|||
|
||||
ret
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Read a response from the server
|
||||
#
|
||||
|
@ -323,7 +323,7 @@ class Client
|
|||
# do this if t was specified as a negative value indicating an infinite
|
||||
# wait cycle. If t were specified as nil it would indicate that no
|
||||
# response parsing is required.
|
||||
timeout((t < 0) ? nil : t) {
|
||||
Timeout.timeout((t < 0) ? nil : t) {
|
||||
# Now, read in the response until we're good to go.
|
||||
begin
|
||||
if self.junk_pipeline
|
||||
|
@ -379,7 +379,7 @@ class Client
|
|||
# Close our side if we aren't pipelining
|
||||
#close if (!pipelining?)
|
||||
|
||||
# if the server said stop pipelining, we listen...
|
||||
# if the server said stop pipelining, we listen...
|
||||
if resp['Connection'] == 'close'
|
||||
#close
|
||||
end
|
||||
|
@ -413,38 +413,38 @@ class Client
|
|||
def pipelining?
|
||||
pipeline
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Return the encoded URI
|
||||
# ['none','hex-normal', 'hex-all', 'u-normal', 'u-all']
|
||||
def set_encode_uri(uri)
|
||||
def set_encode_uri(uri)
|
||||
a = uri
|
||||
self.config['uri_encode_count'].times {
|
||||
a = Rex::Text.uri_encode(a, self.config['uri_encode_mode'])
|
||||
}
|
||||
return a
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Return the encoded query string
|
||||
#
|
||||
def set_encode_qs(qs)
|
||||
a = qs
|
||||
a = qs
|
||||
self.config['uri_encode_count'].times {
|
||||
a = Rex::Text.uri_encode(a, self.config['uri_encode_mode'])
|
||||
}
|
||||
return a
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Return the uri
|
||||
#
|
||||
def set_uri(uri)
|
||||
|
||||
|
||||
if (self.config['uri_dir_self_reference'])
|
||||
uri.gsub!('/', '/./')
|
||||
end
|
||||
|
||||
|
||||
if (self.config['uri_dir_fake_relative'])
|
||||
buf = ""
|
||||
uri.split('/').each do |part|
|
||||
|
@ -457,7 +457,7 @@ class Client
|
|||
end
|
||||
uri = buf
|
||||
end
|
||||
|
||||
|
||||
if (self.config['uri_full_url'])
|
||||
url = self.ssl ? "https" : "http"
|
||||
url << self.config['vhost']
|
||||
|
@ -477,7 +477,7 @@ class Client
|
|||
if (self.config['uri_dir_self_reference'])
|
||||
uri.gsub!('/', '/./')
|
||||
end
|
||||
|
||||
|
||||
if (self.config['uri_dir_fake_relative'])
|
||||
buf = ""
|
||||
uri.split('/').each do |part|
|
||||
|
@ -490,37 +490,37 @@ class Client
|
|||
end
|
||||
uri = buf
|
||||
end
|
||||
|
||||
|
||||
url = uri
|
||||
|
||||
|
||||
if (self.config['uri_full_url'])
|
||||
url = self.ssl ? "https" : "http"
|
||||
url << self.config['vhost']
|
||||
url << (self.port == 80) ? "" : ":#{self.port}"
|
||||
url << uri
|
||||
end
|
||||
|
||||
|
||||
url
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Return the HTTP method string
|
||||
#
|
||||
def set_method(method)
|
||||
ret = method
|
||||
|
||||
|
||||
if (self.config['method_random_valid'])
|
||||
ret = ['GET', 'POST', 'HEAD'][rand(3)]
|
||||
end
|
||||
|
||||
|
||||
if (self.config['method_random_invalid'])
|
||||
ret = Rex::Text.rand_text_alpha(rand(20)+1)
|
||||
end
|
||||
|
||||
|
||||
if (self.config['method_random_case'])
|
||||
ret = Rex::Text.to_rand_case(ret)
|
||||
end
|
||||
|
||||
|
||||
ret
|
||||
end
|
||||
|
||||
|
@ -529,19 +529,19 @@ class Client
|
|||
#
|
||||
def set_version(protocol, version)
|
||||
ret = protocol + "/" + version
|
||||
|
||||
|
||||
if (self.config['version_random_valid'])
|
||||
ret = protocol + "/" + ['1.0', '1.1'][rand(2)]
|
||||
end
|
||||
|
||||
|
||||
if (self.config['version_random_invalid'])
|
||||
ret = Rex::Text.rand_text_alphanumeric(rand(20)+1)
|
||||
end
|
||||
|
||||
|
||||
if (self.config['version_random_case'])
|
||||
ret = Rex::Text.to_rand_case(ret)
|
||||
end
|
||||
|
||||
|
||||
ret << "\r\n"
|
||||
end
|
||||
|
||||
|
@ -558,7 +558,7 @@ class Client
|
|||
end
|
||||
"\r\n" + chunked + "0\r\n\r\n"
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Return the HTTP path info
|
||||
# TODO:
|
||||
|
@ -566,7 +566,7 @@ class Client
|
|||
def set_path_info(path)
|
||||
path ? path : ''
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Return the spacing between the method and uri
|
||||
#
|
||||
|
@ -574,18 +574,18 @@ class Client
|
|||
len = self.config['pad_method_uri_count'].to_i
|
||||
set = " "
|
||||
buf = ""
|
||||
|
||||
|
||||
case self.config['pad_method_uri_type']
|
||||
when 'tab'
|
||||
set = "\t"
|
||||
when 'apache'
|
||||
set = "\t \x0b\x0c\x0d"
|
||||
end
|
||||
|
||||
|
||||
while(buf.length < len)
|
||||
buf << set[ rand(set.length) ]
|
||||
end
|
||||
|
||||
|
||||
return buf
|
||||
end
|
||||
|
||||
|
@ -596,18 +596,18 @@ class Client
|
|||
len = self.config['pad_uri_version_count'].to_i
|
||||
set = " "
|
||||
buf = ""
|
||||
|
||||
|
||||
case self.config['pad_uri_version_type']
|
||||
when 'tab'
|
||||
set = "\t"
|
||||
when 'apache'
|
||||
set = "\t \x0b\x0c\x0d"
|
||||
end
|
||||
|
||||
|
||||
while(buf.length < len)
|
||||
buf << set[ rand(set.length) ]
|
||||
end
|
||||
|
||||
|
||||
return buf
|
||||
end
|
||||
|
||||
|
@ -616,15 +616,15 @@ class Client
|
|||
#
|
||||
def set_uri_prepend
|
||||
prefix = ""
|
||||
|
||||
|
||||
if (self.config['uri_fake_params_start'])
|
||||
prefix << '/%3fa=b/../'
|
||||
end
|
||||
|
||||
|
||||
if (self.config['uri_fake_end'])
|
||||
prefix << '/%20HTTP/1.0/../../'
|
||||
end
|
||||
|
||||
|
||||
prefix
|
||||
end
|
||||
|
||||
|
@ -649,7 +649,7 @@ class Client
|
|||
#
|
||||
# Return the HTTP agent header
|
||||
#
|
||||
def set_agent_header(agent)
|
||||
def set_agent_header(agent)
|
||||
agent ? set_formatted_header("User-Agent", agent) : ""
|
||||
end
|
||||
|
||||
|
@ -664,9 +664,9 @@ class Client
|
|||
# Return the HTTP connection header
|
||||
#
|
||||
def set_connection_header(conn)
|
||||
conn ? set_formatted_header("Connection", conn) : ""
|
||||
conn ? set_formatted_header("Connection", conn) : ""
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Return the content type header
|
||||
#
|
||||
|
@ -697,7 +697,7 @@ class Client
|
|||
if (self.config['pad_fake_headers'])
|
||||
1.upto(self.config['pad_fake_headers_count'].to_i) do |i|
|
||||
buf << set_formatted_header(
|
||||
Rex::Text.rand_text_alphanumeric(rand(32)+1),
|
||||
Rex::Text.rand_text_alphanumeric(rand(32)+1),
|
||||
Rex::Text.rand_text_alphanumeric(rand(32)+1)
|
||||
)
|
||||
end
|
||||
|
@ -706,7 +706,7 @@ class Client
|
|||
headers.each_pair do |var,val|
|
||||
buf << set_formatted_header(var, val)
|
||||
end
|
||||
|
||||
|
||||
buf
|
||||
end
|
||||
|
||||
|
@ -721,7 +721,7 @@ class Client
|
|||
def set_raw_headers(data)
|
||||
data
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Return a formatted header string
|
||||
#
|
||||
|
@ -732,7 +732,7 @@ class Client
|
|||
"#{var}: #{val}\r\n"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
#
|
||||
|
@ -767,11 +767,11 @@ class Client
|
|||
# The proxy list
|
||||
#
|
||||
attr_accessor :proxies
|
||||
|
||||
|
||||
|
||||
# When parsing the request, thunk off the first response from the server, since junk
|
||||
attr_accessor :junk_pipeline
|
||||
|
||||
|
||||
protected
|
||||
|
||||
# https
|
||||
|
@ -779,9 +779,10 @@ protected
|
|||
|
||||
attr_accessor :hostname, :port # :nodoc:
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ require 'rex/proto/dcerpc'
|
|||
require 'rex/socket'
|
||||
|
||||
class Rex::Proto::SMB::Client::UnitTest < Test::Unit::TestCase
|
||||
|
||||
|
||||
Klass = Rex::Proto::SMB::Client
|
||||
|
||||
# Alias over the Rex DCERPC protocol modules
|
||||
|
@ -19,28 +19,28 @@ class Rex::Proto::SMB::Client::UnitTest < Test::Unit::TestCase
|
|||
DCERPCClient = Rex::Proto::DCERPC::Client
|
||||
DCERPCResponse = Rex::Proto::DCERPC::Response
|
||||
DCERPCUUID = Rex::Proto::DCERPC::UUID
|
||||
|
||||
|
||||
def test_smb_open_share
|
||||
|
||||
|
||||
share = 'C$'
|
||||
|
||||
|
||||
write_data = ('A' * 256)
|
||||
filename = 'smb_test.txt'
|
||||
|
||||
begin
|
||||
timeout($_REX_TEST_TIMEOUT) {
|
||||
Timeout.timeout($_REX_TEST_TIMEOUT) {
|
||||
s = Rex::Socket.create_tcp(
|
||||
'PeerHost' => $_REX_TEST_SMB_HOST,
|
||||
'PeerPort' => 139
|
||||
)
|
||||
|
||||
c = Klass.new(s)
|
||||
|
||||
|
||||
# Request a SMB session over NetBIOS
|
||||
# puts "[*] Requesting a SMB session over NetBIOS..."
|
||||
ok = c.session_request()
|
||||
assert_kind_of(Rex::Struct2::CStruct, ok)
|
||||
|
||||
|
||||
# Check for a positive session response
|
||||
# A negative response is 0x83
|
||||
assert_equal(ok.v['Type'], 0x82)
|
||||
|
@ -53,22 +53,22 @@ class Rex::Proto::SMB::Client::UnitTest < Test::Unit::TestCase
|
|||
ok = c.session_setup_ntlmv2($_REX_TEXT_SMB_USER, $_REX_TEXT_SMB_PASS)
|
||||
assert_kind_of(Rex::Struct2::CStruct, ok)
|
||||
assert_not_equal(c.auth_user_id, 0)
|
||||
|
||||
# puts "[*] Connecting to the share..."
|
||||
|
||||
# puts "[*] Connecting to the share..."
|
||||
ok = c.tree_connect(share)
|
||||
assert_kind_of(Rex::Struct2::CStruct, ok)
|
||||
assert_not_equal(c.last_tree_id, 0)
|
||||
|
||||
|
||||
# puts "[*] Opening a file for write..."
|
||||
ok = c.open(filename)
|
||||
assert_kind_of(Rex::Struct2::CStruct, ok)
|
||||
assert_not_equal(c.last_file_id, 0)
|
||||
|
||||
|
||||
# puts "[*] Writing data to the test file..."
|
||||
ok = c.write(c.last_file_id, 0, write_data)
|
||||
assert_kind_of(Rex::Struct2::CStruct, ok)
|
||||
assert_equal(ok['Payload'].v['CountLow'], write_data.length)
|
||||
|
||||
|
||||
# puts "[*] Closing the test file..."
|
||||
ok = c.close(c.last_file_id)
|
||||
assert_kind_of(Rex::Struct2::CStruct, ok)
|
||||
|
@ -76,30 +76,30 @@ class Rex::Proto::SMB::Client::UnitTest < Test::Unit::TestCase
|
|||
# puts "[*] Opening a file for read..."
|
||||
ok = c.open(filename, 1)
|
||||
assert_kind_of(Rex::Struct2::CStruct, ok)
|
||||
assert_not_equal(c.last_file_id, 0)
|
||||
|
||||
assert_not_equal(c.last_file_id, 0)
|
||||
|
||||
# puts "[*] Reading data from the test file..."
|
||||
ok = c.read(c.last_file_id, 0, write_data.length)
|
||||
assert_kind_of(Rex::Struct2::CStruct, ok)
|
||||
assert_equal(ok['Payload'].v['DataLenLow'], write_data.length)
|
||||
|
||||
|
||||
read_data = ok.to_s.slice(
|
||||
ok['Payload'].v['DataOffset'] + 4,
|
||||
ok['Payload'].v['DataLenLow']
|
||||
)
|
||||
)
|
||||
assert_equal(read_data, write_data)
|
||||
|
||||
# puts "[*] Closing the test file..."
|
||||
ok = c.close(c.last_file_id)
|
||||
assert_kind_of(Rex::Struct2::CStruct, ok)
|
||||
|
||||
# puts "[*] Disconnecting from the tree..."
|
||||
|
||||
# puts "[*] Disconnecting from the tree..."
|
||||
ok = c.tree_disconnect
|
||||
assert_kind_of(Rex::Struct2::CStruct, ok)
|
||||
|
||||
|
||||
s.close
|
||||
|
||||
|
||||
|
||||
|
||||
# Reconnect and delete the file
|
||||
s = Rex::Socket.create_tcp(
|
||||
'PeerHost' => $_REX_TEST_SMB_HOST,
|
||||
|
@ -107,12 +107,12 @@ class Rex::Proto::SMB::Client::UnitTest < Test::Unit::TestCase
|
|||
)
|
||||
|
||||
c = Klass.new(s)
|
||||
|
||||
|
||||
# Request a SMB session over NetBIOS
|
||||
# puts "[*] Requesting a SMB session over NetBIOS..."
|
||||
ok = c.session_request()
|
||||
assert_kind_of(Rex::Struct2::CStruct, ok)
|
||||
|
||||
|
||||
# Check for a positive session response
|
||||
# A negative response is 0x83
|
||||
assert_equal(ok.v['Type'], 0x82)
|
||||
|
@ -125,43 +125,43 @@ class Rex::Proto::SMB::Client::UnitTest < Test::Unit::TestCase
|
|||
ok = c.session_setup_ntlmv2($_REX_TEXT_SMB_USER, $_REX_TEXT_SMB_PASS)
|
||||
assert_kind_of(Rex::Struct2::CStruct, ok)
|
||||
assert_not_equal(c.auth_user_id, 0)
|
||||
|
||||
# puts "[*] Connecting to the share..."
|
||||
|
||||
# puts "[*] Connecting to the share..."
|
||||
ok = c.tree_connect(share)
|
||||
assert_kind_of(Rex::Struct2::CStruct, ok)
|
||||
assert_not_equal(c.last_tree_id, 0)
|
||||
|
||||
|
||||
# puts "[*] Deleting the test file..."
|
||||
ok = c.delete(filename)
|
||||
assert_kind_of(Rex::Struct2::CStruct, ok)
|
||||
|
||||
# puts "[*] Diconnecting from the tree..."
|
||||
|
||||
# puts "[*] Diconnecting from the tree..."
|
||||
ok = c.tree_disconnect
|
||||
assert_kind_of(Rex::Struct2::CStruct, ok)
|
||||
|
||||
s.close
|
||||
|
||||
s.close
|
||||
}
|
||||
rescue Timeout::Error
|
||||
flunk('timeout')
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
def test_smb_session_request
|
||||
begin
|
||||
timeout($_REX_TEST_TIMEOUT) {
|
||||
Timeout.timeout($_REX_TEST_TIMEOUT) {
|
||||
s = Rex::Socket.create_tcp(
|
||||
'PeerHost' => $_REX_TEST_SMB_HOST,
|
||||
'PeerPort' => 139
|
||||
)
|
||||
|
||||
c = Klass.new(s)
|
||||
|
||||
|
||||
# Request a SMB session over NetBIOS
|
||||
# puts "[*] Requesting a SMB session over NetBIOS..."
|
||||
ok = c.session_request()
|
||||
assert_kind_of(Rex::Struct2::CStruct, ok)
|
||||
|
||||
|
||||
# Check for a positive session response
|
||||
# A negative response is 0x83
|
||||
assert_equal(ok.v['Type'], 0x82)
|
||||
|
@ -173,13 +173,13 @@ class Rex::Proto::SMB::Client::UnitTest < Test::Unit::TestCase
|
|||
# puts "[*] Authenticating with NTLMv2..."
|
||||
ok = c.session_setup_ntlmv2
|
||||
assert_kind_of(Rex::Struct2::CStruct, ok)
|
||||
|
||||
# puts "[*] Authenticating with NTLMv1..."
|
||||
|
||||
# puts "[*] Authenticating with NTLMv1..."
|
||||
ok = c.session_setup_ntlmv1
|
||||
assert_kind_of(Rex::Struct2::CStruct, ok)
|
||||
|
||||
|
||||
# puts "[*] Authenticating with clear text passwords..."
|
||||
begin
|
||||
begin
|
||||
ok = c.session_setup_clear
|
||||
assert_kind_of(Rex::Struct2::CStruct, ok)
|
||||
rescue Rex::Proto::SMB::Exceptions::ErrorCode
|
||||
|
@ -188,28 +188,28 @@ class Rex::Proto::SMB::Client::UnitTest < Test::Unit::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
# puts "[*] Connecting to IPC$..."
|
||||
# puts "[*] Connecting to IPC$..."
|
||||
ok = c.tree_connect
|
||||
assert_kind_of(Rex::Struct2::CStruct, ok)
|
||||
|
||||
# puts "[*] Opening the \BROWSER pipe..."
|
||||
# puts "[*] Opening the \BROWSER pipe..."
|
||||
ok = c.create_pipe('\BROWSER')
|
||||
assert_kind_of(Rex::Struct2::CStruct, ok)
|
||||
|
||||
|
||||
vers = DCERPCUUID.vers_by_name('SRVSVC')
|
||||
uuid = DCERPCUUID.uuid_by_name('SRVSVC')
|
||||
bind, ctx = DCERPCPacket.make_bind_fake_multi(uuid, vers)
|
||||
|
||||
# puts "[*] Binding to the Server Service..."
|
||||
# puts "[*] Binding to the Server Service..."
|
||||
ok = c.trans_named_pipe(c.last_file_id, bind)
|
||||
assert_kind_of(Rex::Struct2::CStruct, ok)
|
||||
|
||||
|
||||
data = ok.to_s.slice(
|
||||
ok['Payload'].v['DataOffset'] + 4,
|
||||
ok['Payload'].v['DataCount']
|
||||
)
|
||||
assert_not_equal(data, nil)
|
||||
|
||||
|
||||
resp = DCERPCResponse.new(data)
|
||||
assert_equal(resp.type, 12)
|
||||
}
|
||||
|
@ -218,5 +218,6 @@ class Rex::Proto::SMB::Client::UnitTest < Test::Unit::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ require 'rex/proto/dcerpc'
|
|||
require 'rex/socket'
|
||||
|
||||
class Rex::Proto::SMB::SimpleClient::UnitTest < Test::Unit::TestCase
|
||||
|
||||
|
||||
Klass = Rex::Proto::SMB::SimpleClient
|
||||
|
||||
# Alias over the Rex DCERPC protocol modules
|
||||
|
@ -17,28 +17,28 @@ class Rex::Proto::SMB::SimpleClient::UnitTest < Test::Unit::TestCase
|
|||
DCERPCResponse = Rex::Proto::DCERPC::Response
|
||||
DCERPCUUID = Rex::Proto::DCERPC::UUID
|
||||
XCEPT = Rex::Proto::SMB::Exceptions
|
||||
|
||||
|
||||
FILE_CREATE = 0x10
|
||||
FILE_TRUNC = 0x02
|
||||
FILE_OPEN = 0x01
|
||||
|
||||
|
||||
|
||||
|
||||
def test_smb_open_share
|
||||
user = 'SMBTest'
|
||||
pass = 'SMBTest'
|
||||
share = 'C$'
|
||||
|
||||
|
||||
write_data = ('A' * (1024 * 8))
|
||||
filename = 'smb_tester.txt'
|
||||
begin
|
||||
timeout($_REX_TEST_TIMEOUT) {
|
||||
Timeout.timeout($_REX_TEST_TIMEOUT) {
|
||||
s = Rex::Socket.create_tcp(
|
||||
'PeerHost' => $_REX_TEST_SMB_HOST,
|
||||
'PeerPort' => 445
|
||||
)
|
||||
|
||||
c = Klass.new(s, true)
|
||||
|
||||
|
||||
begin
|
||||
c.login('*SMBSERVER', user, pass)
|
||||
rescue XCEPT::LoginError
|
||||
|
@ -46,19 +46,19 @@ class Rex::Proto::SMB::SimpleClient::UnitTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
c.connect(share)
|
||||
|
||||
|
||||
f = c.open(filename, 'rwct')
|
||||
f << write_data
|
||||
f.close
|
||||
|
||||
|
||||
f = c.open(filename, 'ro')
|
||||
d = f.read()
|
||||
f.close
|
||||
|
||||
|
||||
c.delete(filename)
|
||||
c.disconnect(share)
|
||||
|
||||
s.close
|
||||
s.close
|
||||
}
|
||||
rescue Timeout::Error
|
||||
flunk('timeout')
|
||||
|
@ -67,7 +67,7 @@ class Rex::Proto::SMB::SimpleClient::UnitTest < Test::Unit::TestCase
|
|||
|
||||
def test_smb_dcerpc
|
||||
begin
|
||||
timeout($_REX_TEST_TIMEOUT) {
|
||||
Timeout.timeout($_REX_TEST_TIMEOUT) {
|
||||
s = Rex::Socket.create_tcp(
|
||||
'PeerHost' => $_REX_TEST_SMB_HOST,
|
||||
'PeerPort' => 445
|
||||
|
@ -86,13 +86,13 @@ class Rex::Proto::SMB::SimpleClient::UnitTest < Test::Unit::TestCase
|
|||
|
||||
c.connect('IPC$')
|
||||
f = c.create_pipe('\BROWSER')
|
||||
|
||||
|
||||
bind, ctx = DCERPCPacket.make_bind_fake_multi(
|
||||
'4b324fc8-1670-01d3-1278-5a47bf6ee188', '3.0',
|
||||
10,
|
||||
10,
|
||||
4
|
||||
)
|
||||
|
||||
|
||||
# Evasion techniques:
|
||||
# 1) Write the bind out a few bytes at a time with a random offset
|
||||
# 2) Read the response back a few bytes at a time with a random offset
|
||||
|
@ -101,7 +101,7 @@ class Rex::Proto::SMB::SimpleClient::UnitTest < Test::Unit::TestCase
|
|||
while (bind.length > 0)
|
||||
f.write( bind.slice!(0, (rand(20)+5)), rand(1024)+1 )
|
||||
end
|
||||
|
||||
|
||||
d = ''
|
||||
# Read the response back a few bytes a time
|
||||
begin
|
||||
|
@ -118,10 +118,11 @@ class Rex::Proto::SMB::SimpleClient::UnitTest < Test::Unit::TestCase
|
|||
assert_equal(r.ack_result[ctx-0], 0)
|
||||
assert_equal(r.ack_result[ctx-1], 2)
|
||||
|
||||
s.close
|
||||
s.close
|
||||
}
|
||||
rescue Timeout::Error
|
||||
flunk('timeout')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -56,8 +56,8 @@ class Rex::Socket::Comm::Local
|
|||
|
||||
sock
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Creates a socket using the supplied Parameter instance.
|
||||
#
|
||||
|
@ -65,7 +65,7 @@ class Rex::Socket::Comm::Local
|
|||
|
||||
# Whether to use IPv6 addressing
|
||||
usev6 = false
|
||||
|
||||
|
||||
# Detect IPv6 addresses and enable IPv6 accordingly
|
||||
if ( Rex::Socket.support_ipv6?())
|
||||
|
||||
|
@ -77,23 +77,23 @@ class Rex::Socket::Comm::Local
|
|||
# Force IPv6 mode for non-connected UDP sockets
|
||||
if (type == ::Socket::SOCK_DGRAM and not param.peerhost)
|
||||
# FreeBSD allows IPv6 socket creation, but throws an error on sendto()
|
||||
|
||||
|
||||
if (not Rex::Compat.is_freebsd())
|
||||
usev6 = true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local = Rex::Socket.resolv_nbo(param.localhost) if param.localhost
|
||||
peer = Rex::Socket.resolv_nbo(param.peerhost) if param.peerhost
|
||||
|
||||
|
||||
if (local and local.length == 16)
|
||||
usev6 = true
|
||||
usev6 = true
|
||||
end
|
||||
|
||||
|
||||
if (peer and peer.length == 16)
|
||||
usev6 = true
|
||||
usev6 = true
|
||||
end
|
||||
|
||||
|
||||
if (usev6)
|
||||
if (local and local.length == 4)
|
||||
if (local == "\x00\x00\x00\x00")
|
||||
|
@ -104,7 +104,7 @@ class Rex::Socket::Comm::Local
|
|||
param.localhost = '::ffff:' + Rex::Socket.getaddress(param.localhost)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if (peer and peer.length == 4)
|
||||
if (peer == "\x00\x00\x00\x00")
|
||||
param.peerhost = '::'
|
||||
|
@ -114,28 +114,28 @@ class Rex::Socket::Comm::Local
|
|||
param.peerhost = '::ffff:' + Rex::Socket.getaddress(param.peerhost)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
param.v6 = true
|
||||
end
|
||||
end
|
||||
else
|
||||
# No IPv6 support
|
||||
param.v6 = false
|
||||
end
|
||||
|
||||
|
||||
# Notify handlers of the before socket create event.
|
||||
self.instance.notify_before_socket_create(self, param)
|
||||
|
||||
# Create the socket
|
||||
sock = nil
|
||||
if (param.v6)
|
||||
sock = ::Socket.new(::Socket::AF_INET6, type, proto)
|
||||
sock = ::Socket.new(::Socket::AF_INET6, type, proto)
|
||||
else
|
||||
sock = ::Socket.new(::Socket::AF_INET, type, proto)
|
||||
end
|
||||
|
||||
# Bind to a given local address and/or port if they are supplied
|
||||
if (param.localhost || param.localport)
|
||||
begin
|
||||
begin
|
||||
sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEADDR, true)
|
||||
|
||||
sock.bind(Rex::Socket.to_sockaddr(param.localhost, param.localport))
|
||||
|
@ -145,7 +145,7 @@ class Rex::Socket::Comm::Local
|
|||
raise Rex::AddressInUse.new(param.localhost, param.localport), caller
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Configure broadcast support for all datagram sockets
|
||||
if (type == ::Socket::SOCK_DGRAM)
|
||||
sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_BROADCAST, true)
|
||||
|
@ -182,21 +182,21 @@ class Rex::Socket::Comm::Local
|
|||
end
|
||||
|
||||
begin
|
||||
timeout(param.timeout) do
|
||||
Timeout.timeout(param.timeout) do
|
||||
sock.connect(Rex::Socket.to_sockaddr(ip, port))
|
||||
end
|
||||
rescue ::Timeout::Error
|
||||
raise ::Errno::ETIMEDOUT
|
||||
end
|
||||
end
|
||||
|
||||
rescue ::Errno::EHOSTUNREACH,::Errno::ENETDOWN,::Errno::ENETUNREACH,::Errno::ENETRESET,::Errno::EHOSTDOWN,::Errno::EACCES,::Errno::EINVAL,::Errno::EADDRNOTAVAIL
|
||||
sock.close
|
||||
raise Rex::HostUnreachable.new(param.peerhost, param.peerport), caller
|
||||
|
||||
|
||||
rescue Errno::ETIMEDOUT
|
||||
sock.close
|
||||
raise Rex::ConnectionTimeout.new(param.peerhost, param.peerport), caller
|
||||
|
||||
|
||||
rescue ::Errno::ECONNRESET,::Errno::ECONNREFUSED,::Errno::ENOTCONN,::Errno::ECONNABORTED
|
||||
sock.close
|
||||
raise Rex::ConnectionRefused.new(param.peerhost, param.peerport), caller
|
||||
|
@ -224,15 +224,15 @@ class Rex::Socket::Comm::Local
|
|||
end
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
# Now extend the socket with SSL and perform the handshake
|
||||
if(param.bare? == false and param.ssl)
|
||||
klass = Rex::Socket::SslTcp
|
||||
sock.extend(klass)
|
||||
sock.initsock(param)
|
||||
sock.initsock(param)
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
# Notify handlers that a socket has been created.
|
||||
|
@ -240,9 +240,9 @@ class Rex::Socket::Comm::Local
|
|||
|
||||
sock
|
||||
end
|
||||
|
||||
|
||||
def self.proxy(sock, type, host, port)
|
||||
|
||||
|
||||
#$stdout.print("PROXY\n")
|
||||
case type.downcase
|
||||
when 'http'
|
||||
|
@ -251,7 +251,7 @@ class Rex::Socket::Comm::Local
|
|||
if (size != setup.length)
|
||||
raise ArgumentError, "Wrote less data than expected to the http proxy"
|
||||
end
|
||||
|
||||
|
||||
begin
|
||||
ret = sock.get_once(39,30)
|
||||
rescue IOError
|
||||
|
@ -299,11 +299,11 @@ class Rex::Socket::Comm::Local
|
|||
end
|
||||
|
||||
if (Rex::Socket.is_ipv4?(host))
|
||||
addr = Rex::Socket.gethostbyname(host)[3]
|
||||
addr = Rex::Socket.gethostbyname(host)[3]
|
||||
setup = [5,1,0,1].pack('C4') + addr + [port.to_i].pack('n')
|
||||
elsif (Rex::Socket.support_ipv6? and Rex::Socket.is_ipv6?(host))
|
||||
# IPv6 stuff all untested
|
||||
addr = Rex::Socket.gethostbyname(host)[3]
|
||||
addr = Rex::Socket.gethostbyname(host)[3]
|
||||
setup = [5,1,0,4].pack('C4') + addr + [port.to_i].pack('n')
|
||||
else
|
||||
# Then it must be a domain name.
|
||||
|
@ -339,7 +339,7 @@ class Rex::Socket::Comm::Local
|
|||
# Registration
|
||||
#
|
||||
##
|
||||
|
||||
|
||||
def self.register_event_handler(handler) # :nodoc:
|
||||
self.instance.register_event_handler(handler)
|
||||
end
|
||||
|
@ -353,3 +353,4 @@ class Rex::Socket::Comm::Local
|
|||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ class Event
|
|||
self.mutex = Mutex.new
|
||||
self.cond = ConditionVariable.new
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Sets the event and wakes up anyone who was waiting.
|
||||
#
|
||||
|
@ -33,7 +33,7 @@ class Event
|
|||
self.param = param
|
||||
|
||||
self.mutex.synchronize {
|
||||
# If this event does not automatically reset its state,
|
||||
# If this event does not automatically reset its state,
|
||||
# set the state to true
|
||||
if (auto_reset == false)
|
||||
self.state = true
|
||||
|
@ -57,23 +57,23 @@ class Event
|
|||
alias notify set
|
||||
|
||||
#
|
||||
# Waits for the event to become signaled. Timeout is measured in
|
||||
# Waits for the event to become signaled. Timeout is measured in
|
||||
# seconds. Raises TimeoutError if the condition does not become signaled.
|
||||
#
|
||||
|
||||
|
||||
begin
|
||||
# XXX: we need to replace this code
|
||||
# continuations slow down YARV
|
||||
require "continuation" if not defined? callcc
|
||||
rescue ::LoadError
|
||||
end
|
||||
|
||||
|
||||
def wait(t = Infinite)
|
||||
callcc { |ctx|
|
||||
self.mutex.synchronize {
|
||||
ctx.call if (self.state == true)
|
||||
|
||||
timeout(t) {
|
||||
Timeout.timeout(t) {
|
||||
self.cond.wait(self.mutex)
|
||||
}
|
||||
}
|
||||
|
@ -91,3 +91,4 @@ end
|
|||
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ end
|
|||
#
|
||||
class RequestId
|
||||
MAX_REQUEST_ID = 2**31
|
||||
|
||||
|
||||
def initialize
|
||||
@lock = Mutex.new
|
||||
@request_id = rand(MAX_REQUEST_ID)
|
||||
|
@ -90,7 +90,7 @@ class RequestId
|
|||
return @request_id
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def force_next(next_id)
|
||||
new_request_id = next_id.to_i
|
||||
if new_request_id < 1 || new_request_id >= MAX_REQUEST_ID
|
||||
|
@ -102,7 +102,7 @@ class RequestId
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
# == SNMP Manager
|
||||
#
|
||||
|
@ -118,7 +118,7 @@ end
|
|||
# manager.close
|
||||
#
|
||||
# == Symbolic Object Names
|
||||
#
|
||||
#
|
||||
# Symbolic names for SNMP object IDs can be used as parameters to the
|
||||
# APIs in this class if the MIB modules are imported and the names of the
|
||||
# MIBs are included in the MibModules configuration parameter.
|
||||
|
@ -131,7 +131,7 @@ end
|
|||
#
|
||||
# Additional modules may be imported using the MIB class. The
|
||||
# current implementation of the importing code requires that the
|
||||
# external 'smidump' tool is available in your PATH. This tool can be
|
||||
# external 'smidump' tool is available in your PATH. This tool can be
|
||||
# obtained from the libsmi website at
|
||||
# http://www.ibr.cs.tu-bs.de/projects/libsmi/ .
|
||||
#
|
||||
|
@ -169,17 +169,17 @@ class Manager
|
|||
:MibModules => ["SNMPv2-SMI", "SNMPv2-MIB", "IF-MIB", "IP-MIB", "TCP-MIB", "UDP-MIB"]}
|
||||
|
||||
@@request_id = RequestId.new
|
||||
|
||||
|
||||
##
|
||||
# Retrieves the current configuration of this Manager.
|
||||
#
|
||||
attr_reader :config
|
||||
|
||||
|
||||
##
|
||||
# Retrieves the MIB for this Manager.
|
||||
#
|
||||
attr_reader :mib
|
||||
|
||||
|
||||
def initialize(config = {})
|
||||
if block_given?
|
||||
warn "SNMP::Manager::new() does not take block; use SNMP::Manager::open() instead"
|
||||
|
@ -200,7 +200,7 @@ class Manager
|
|||
@mib = MIB.new
|
||||
load_modules(@config[:MibModules], @config[:MibDir])
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
# Creates a Manager but also takes an optional block and automatically
|
||||
# closes the transport connection used by this manager after the block
|
||||
|
@ -216,18 +216,18 @@ class Manager
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
# Close the transport connection for this manager.
|
||||
#
|
||||
def close
|
||||
@transport.close
|
||||
end
|
||||
|
||||
|
||||
def load_module(name)
|
||||
@mib.load_module(name)
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
# Sends a get request for the supplied list of ObjectId or VarBind
|
||||
# objects.
|
||||
|
@ -261,7 +261,7 @@ class Manager
|
|||
get(object_list).vb_list.first.value
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
# Sends a get-next request for the supplied list of ObjectId or VarBind
|
||||
# objects.
|
||||
|
@ -273,7 +273,7 @@ class Manager
|
|||
request = GetNextRequest.new(@@request_id.next, varbind_list)
|
||||
try_request(request)
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
# Sends a get-bulk request. The non_repeaters parameter specifies
|
||||
# the number of objects in the object_list to be retrieved once. The
|
||||
|
@ -289,7 +289,7 @@ class Manager
|
|||
max_repetitions)
|
||||
try_request(request)
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
# Sends a set request using the supplied list of VarBind objects.
|
||||
#
|
||||
|
@ -312,7 +312,7 @@ class Manager
|
|||
#
|
||||
# generic_trap: The generic trap identifier. One of :coldStart,
|
||||
# :warmStart, :linkDown, :linkUp, :authenticationFailure,
|
||||
# :egpNeighborLoss, or :enterpriseSpecific
|
||||
# :egpNeighborLoss, or :enterpriseSpecific
|
||||
#
|
||||
# specific_trap: An integer representing the specific trap type for
|
||||
# an enterprise-specific trap.
|
||||
|
@ -320,7 +320,7 @@ class Manager
|
|||
# timestamp: An integer respresenting the number of hundredths of
|
||||
# a second that this system has been up.
|
||||
#
|
||||
# object_list: A list of additional varbinds to send with the trap.
|
||||
# object_list: A list of additional varbinds to send with the trap.
|
||||
#
|
||||
# For example:
|
||||
#
|
||||
|
@ -343,7 +343,7 @@ class Manager
|
|||
trap = SNMPv1_Trap.new(ent_oid, agent_ip, generic_trap, specific_int, ticks, vb_list)
|
||||
send_request(trap, @community, @host, @trap_port)
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
# Sends an SNMPv2c style trap.
|
||||
#
|
||||
|
@ -353,16 +353,16 @@ class Manager
|
|||
# trap_oid: An ObjectId or String with the OID identifier for this
|
||||
# trap.
|
||||
#
|
||||
# object_list: A list of additional varbinds to send with the trap.
|
||||
# object_list: A list of additional varbinds to send with the trap.
|
||||
#
|
||||
def trap_v2(sys_up_time, trap_oid, object_list=[])
|
||||
vb_list = create_trap_vb_list(sys_up_time, trap_oid, object_list)
|
||||
trap = SNMPv2_Trap.new(@@request_id.next, vb_list)
|
||||
send_request(trap, @community, @host, @trap_port)
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
# Sends an inform request using the supplied varbind list.
|
||||
# Sends an inform request using the supplied varbind list.
|
||||
#
|
||||
# sys_up_time: An integer respresenting the number of hundredths of
|
||||
# a second that this system has been up.
|
||||
|
@ -370,14 +370,14 @@ class Manager
|
|||
# trap_oid: An ObjectId or String with the OID identifier for this
|
||||
# inform request.
|
||||
#
|
||||
# object_list: A list of additional varbinds to send with the inform.
|
||||
# object_list: A list of additional varbinds to send with the inform.
|
||||
#
|
||||
def inform(sys_up_time, trap_oid, object_list=[])
|
||||
vb_list = create_trap_vb_list(sys_up_time, trap_oid, object_list)
|
||||
request = InformRequest.new(@@request_id.next, vb_list)
|
||||
try_request(request, @community, @host, @trap_port)
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
# Helper method for building VarBindList for trap and inform requests.
|
||||
#
|
||||
|
@ -387,7 +387,7 @@ class Manager
|
|||
trap_vb = VarBind.new(SNMP::SNMP_TRAP_OID_OID, @mib.oid(trap_oid))
|
||||
VarBindList.new([uptime_vb, trap_vb, *vb_args])
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
# Walks a list of ObjectId or VarBind objects using get_next until
|
||||
# the response to the first OID in the list reaches the end of its
|
||||
|
@ -407,7 +407,7 @@ class Manager
|
|||
# end
|
||||
#
|
||||
# SNMP::Manager.open(:Host => "localhost") do |manager|
|
||||
# manager.walk(["ifIndex", "ifDescr"]) do |index, descr|
|
||||
# manager.walk(["ifIndex", "ifDescr"]) do |index, descr|
|
||||
# puts "#{index.value} #{descr.value}"
|
||||
# end
|
||||
# end
|
||||
|
@ -420,7 +420,7 @@ class Manager
|
|||
# Note: If you are getting back rows where all columns have a value of
|
||||
# NoSuchInstance then your index column is probably missing one of the
|
||||
# rows. Choose an index column that includes all indexes for the table.
|
||||
#
|
||||
#
|
||||
def walk(object_list, index_column=0)
|
||||
raise ArgumentError, "expected a block to be given" unless block_given?
|
||||
vb_list = @mib.varbind_list(object_list, :NullValue)
|
||||
|
@ -433,7 +433,7 @@ class Manager
|
|||
loop do
|
||||
vb_list = get_next(vb_list).vb_list
|
||||
index_vb = vb_list[index_column]
|
||||
break if EndOfMibView == index_vb.value
|
||||
break if EndOfMibView == index_vb.value
|
||||
stop_oid = index_vb.name
|
||||
if stop_oid <= last_oid
|
||||
warn "OIDs are not increasing, #{last_oid} followed by #{stop_oid}"
|
||||
|
@ -449,7 +449,7 @@ class Manager
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
# Helper method for walk. Checks all of the VarBinds in vb_list to
|
||||
# make sure that the row indices match. If the row index does not
|
||||
|
@ -462,7 +462,7 @@ class Manager
|
|||
row_index = index_vb.name.index(start_vb.name)
|
||||
vb_list.each_index do |i|
|
||||
if i != index_column
|
||||
expected_oid = start_list[i].name + row_index
|
||||
expected_oid = start_list[i].name + row_index
|
||||
if vb_list[i].name != expected_oid
|
||||
vb_list[i] = VarBind.new(expected_oid, NoSuchInstance)
|
||||
end
|
||||
|
@ -471,7 +471,7 @@ class Manager
|
|||
vb_list
|
||||
end
|
||||
private :validate_row
|
||||
|
||||
|
||||
##
|
||||
# Set the next request-id instead of letting it be generated
|
||||
# automatically. This method is useful for testing and debugging.
|
||||
|
@ -479,7 +479,7 @@ class Manager
|
|||
def next_request_id=(request_id)
|
||||
@@request_id.force_next(request_id)
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def warn(message)
|
||||
|
@ -487,16 +487,16 @@ class Manager
|
|||
location = trace[0].sub(/:in.*/,'')
|
||||
Kernel::warn "#{location}: warning: #{message}"
|
||||
end
|
||||
|
||||
|
||||
def load_modules(module_list, mib_dir)
|
||||
module_list.each { |m| @mib.load_module(m, mib_dir) }
|
||||
end
|
||||
|
||||
|
||||
def try_request(request, community=@community, host=@host, port=@port)
|
||||
(@retries.to_i + 1).times do |n|
|
||||
send_request(request, community, host, port)
|
||||
begin
|
||||
timeout(@timeout) do
|
||||
Timeout.timeout(@timeout) do
|
||||
return get_response(request)
|
||||
end
|
||||
rescue Timeout::Error
|
||||
|
@ -505,12 +505,12 @@ class Manager
|
|||
end
|
||||
raise RequestTimeout, "host #{@config[:Host]} not responding", caller
|
||||
end
|
||||
|
||||
|
||||
def send_request(request, community, host, port)
|
||||
message = Message.new(@snmp_version, community, request)
|
||||
@transport.send(message.encode, host, port)
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
# Wait until response arrives. Ignore responses with mismatched IDs;
|
||||
# these responses are typically from previous requests that timed out
|
||||
|
@ -531,7 +531,7 @@ class UDPServerTransport
|
|||
@socket = UDPSocket.open
|
||||
@socket.bind(host, port)
|
||||
end
|
||||
|
||||
|
||||
def close
|
||||
@socket.close
|
||||
end
|
||||
|
@ -539,7 +539,7 @@ class UDPServerTransport
|
|||
def send(data, host, port)
|
||||
@socket.send(data, 0, host, port)
|
||||
end
|
||||
|
||||
|
||||
def recvfrom(max_bytes)
|
||||
data, host_info = @socket.recvfrom(max_bytes)
|
||||
flags, host_port, host_name, host_ip = host_info
|
||||
|
@ -571,7 +571,7 @@ class TrapListener
|
|||
:MaxReceiveBytes => 8000}
|
||||
|
||||
NULL_HANDLER = Proc.new {}
|
||||
|
||||
|
||||
##
|
||||
# Start a trap handler thread. If a block is provided then the block
|
||||
# is executed before trap handling begins. This block is typically used
|
||||
|
@ -598,7 +598,7 @@ class TrapListener
|
|||
@lock = Mutex.new
|
||||
@handler_thread = Thread.new(self) { |m| process_traps(m) }
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
# Define the default trap handler. The default trap handler block is
|
||||
# executed only if no other block is applicable. This handler should
|
||||
|
@ -608,7 +608,7 @@ class TrapListener
|
|||
raise ArgumentError, "a block must be provided" unless block
|
||||
@lock.synchronize { @default_handler = block }
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
# Define a trap handler block for a specific trap ObjectId. This handler
|
||||
# only applies to SNMPv2 traps. Note that symbolic OIDs are not
|
||||
|
@ -627,7 +627,7 @@ class TrapListener
|
|||
raise ArgumentError, "a block must be provided" unless block
|
||||
@lock.synchronize { @v1_handler = block }
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
# Define a trap handler block for all SNMPv2c traps. The trap yielded
|
||||
# to the block will always be an SNMPv2_Trap. Note that InformRequest
|
||||
|
@ -638,7 +638,7 @@ class TrapListener
|
|||
raise ArgumentError, "a block must be provided" unless block
|
||||
@lock.synchronize { @v2c_handler = block }
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
# Joins the current thread to the trap handler thread.
|
||||
#
|
||||
|
@ -647,7 +647,7 @@ class TrapListener
|
|||
def join
|
||||
@handler_thread.join
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
# Stops the trap handler thread and releases the socket.
|
||||
#
|
||||
|
@ -657,12 +657,12 @@ class TrapListener
|
|||
@handler_thread.exit
|
||||
@transport.close
|
||||
end
|
||||
|
||||
|
||||
alias kill exit
|
||||
alias terminate exit
|
||||
|
||||
|
||||
private
|
||||
|
||||
|
||||
def process_traps(trap_listener)
|
||||
@handler_init.call(trap_listener) if @handler_init
|
||||
loop do
|
||||
|
@ -681,11 +681,11 @@ class TrapListener
|
|||
puts "Error handling trap: #{e}"
|
||||
puts e.backtrace.join("\n")
|
||||
puts "Received data:"
|
||||
p data
|
||||
p data
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def select_handler(trap)
|
||||
@lock.synchronize do
|
||||
if trap.kind_of?(SNMPv2_Trap)
|
||||
|
@ -715,3 +715,4 @@ class TrapListener
|
|||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue