6b4eb9a8e2
This change adds two new Rex exceptions and changes the local comm to raise the right one depending on the circumstances. The problem with the existing model is that failed binds and failed connections both raised the same exception. This change is backwards compatible with modules that rescue Rex::AddressInUse in additi on to Rex::ConnectionError. There were two corner cases that rescued Rex::AddressInUse specifically: 1. The 'r'-services mixin and modules caught the old exception when handling bind errors. These have been updated to use BindFailed 2. The meterpreter client had a catch for the old exception when the socket reports a bad destination (usually a network connection dropped). This has been updat ed to use InvalidDestination as that was the intention prior to this change. Since AddressInUse was part of ConnectionError, modules and mixins which caught both in the same rescue have been updated to just catch ConnectionError.
308 lines
5.2 KiB
Ruby
308 lines
5.2 KiB
Ruby
# -*- coding: binary -*-
|
|
|
|
module Rex
|
|
|
|
###
|
|
#
|
|
# Base mixin for all exceptions that can be thrown from inside Rex.
|
|
#
|
|
###
|
|
module Exception
|
|
end
|
|
|
|
###
|
|
#
|
|
# This exception is raised when a timeout occurs.
|
|
#
|
|
###
|
|
class TimeoutError < Interrupt
|
|
include Exception
|
|
|
|
def to_s
|
|
"Operation timed out."
|
|
end
|
|
end
|
|
|
|
###
|
|
#
|
|
# This exception is raised when a method is called or a feature is used that
|
|
# is not implemented.
|
|
#
|
|
###
|
|
class NotImplementedError < ::NotImplementedError
|
|
include Exception
|
|
|
|
def to_s
|
|
"The requested method is not implemented."
|
|
end
|
|
end
|
|
|
|
###
|
|
#
|
|
# This exception is raised when a generalized runtime error occurs.
|
|
#
|
|
###
|
|
class RuntimeError < ::RuntimeError
|
|
include Exception
|
|
end
|
|
|
|
###
|
|
#
|
|
# This exception is raised when an invalid argument is supplied to a method.
|
|
#
|
|
###
|
|
class ArgumentError < ::ArgumentError
|
|
include Exception
|
|
|
|
def initialize(message = nil)
|
|
@message = message
|
|
end
|
|
|
|
def to_s
|
|
str = 'An invalid argument was specified.'
|
|
if @message
|
|
str << " #{@message}"
|
|
end
|
|
str
|
|
end
|
|
end
|
|
|
|
###
|
|
#
|
|
# This exception is raised when an argument that was supplied to a method
|
|
# could not be parsed correctly.
|
|
#
|
|
###
|
|
class ArgumentParseError < ::ArgumentError
|
|
include Exception
|
|
|
|
def to_s
|
|
"The argument could not be parsed correctly."
|
|
end
|
|
end
|
|
|
|
###
|
|
#
|
|
# This exception is raised when an argument is ambiguous.
|
|
#
|
|
###
|
|
class AmbiguousArgumentError < ::RuntimeError
|
|
include Exception
|
|
|
|
def initialize(name = nil)
|
|
@name = name
|
|
end
|
|
|
|
def to_s
|
|
"The name #{@name} is ambiguous."
|
|
end
|
|
end
|
|
|
|
###
|
|
#
|
|
# This error is thrown when a stream is detected as being closed.
|
|
#
|
|
###
|
|
class StreamClosedError < ::IOError
|
|
include Exception
|
|
|
|
def initialize(stream)
|
|
@stream = stream
|
|
end
|
|
|
|
def stream
|
|
@stream
|
|
end
|
|
|
|
def to_s
|
|
"Stream #{@stream} is closed."
|
|
end
|
|
end
|
|
|
|
##
|
|
#
|
|
# Socket exceptions
|
|
#
|
|
##
|
|
|
|
###
|
|
#
|
|
# This exception is raised when a general socket error occurs.
|
|
#
|
|
###
|
|
module SocketError
|
|
include Exception
|
|
|
|
def to_s
|
|
"A socket error occurred."
|
|
end
|
|
end
|
|
|
|
###
|
|
#
|
|
# This exception is raised when there is some kind of error related to
|
|
# communication with a host.
|
|
#
|
|
###
|
|
module HostCommunicationError
|
|
def initialize(addr = nil, port = nil)
|
|
self.host = addr
|
|
self.port = port
|
|
end
|
|
|
|
#
|
|
# This method returns a printable address and optional port associated
|
|
# with the host that triggered the exception.
|
|
#
|
|
def addr_to_s
|
|
if host and port
|
|
"(#{host}:#{port})"
|
|
elsif host
|
|
"(#{host})"
|
|
else
|
|
""
|
|
end
|
|
end
|
|
|
|
attr_accessor :host, :port
|
|
end
|
|
|
|
|
|
###
|
|
#
|
|
# This is a generic exception for errors that cause a connection to fail.
|
|
#
|
|
###
|
|
class ConnectionError < ::IOError
|
|
include SocketError
|
|
include HostCommunicationError
|
|
end
|
|
|
|
###
|
|
#
|
|
# This exception is raised when a connection attempt fails because the remote
|
|
# side refused the connection.
|
|
#
|
|
###
|
|
class ConnectionRefused < ConnectionError
|
|
def to_s
|
|
"The connection was refused by the remote host #{addr_to_s}."
|
|
end
|
|
end
|
|
|
|
###
|
|
#
|
|
# This exception is raised when a connection attempt fails because the remote
|
|
# side is unreachable.
|
|
#
|
|
###
|
|
class HostUnreachable < ConnectionError
|
|
def to_s
|
|
"The host #{addr_to_s} was unreachable."
|
|
end
|
|
end
|
|
|
|
###
|
|
#
|
|
# This exception is raised when a connection attempt times out.
|
|
#
|
|
###
|
|
class ConnectionTimeout < ConnectionError
|
|
def to_s
|
|
"The connection timed out #{addr_to_s}."
|
|
end
|
|
end
|
|
|
|
###
|
|
#
|
|
# This connection error is raised when an attempt is made to connect
|
|
# to a broadcast or network address.
|
|
#
|
|
###
|
|
class InvalidDestination < ConnectionError
|
|
include SocketError
|
|
include HostCommunicationError
|
|
|
|
def to_s
|
|
"The destination is invalid: #{addr_to_s}."
|
|
end
|
|
end
|
|
|
|
###
|
|
#
|
|
# This exception is raised when an attempt to use an address or port that is
|
|
# already in use or onot available occurs. such as binding to a host on a
|
|
# given port that is already in use, or when a bind address is specified that
|
|
# is not available to the host.
|
|
#
|
|
###
|
|
class BindFailed < ::ArgumentError
|
|
include SocketError
|
|
include HostCommunicationError
|
|
|
|
def to_s
|
|
"The address is already in use or unavailable: #{addr_to_s}."
|
|
end
|
|
end
|
|
|
|
##
|
|
#
|
|
# This exception is listed for backwards compatibility. We had been
|
|
# using AddressInUse as the exception for both bind errors and connection
|
|
# errors triggered by connection attempts to broadcast and network addresses.
|
|
# The two classes above have split this into their respective sources, but
|
|
# callers may still expect the old behavior.
|
|
#
|
|
##
|
|
class AddressInUse < ConnectionError
|
|
include SocketError
|
|
include HostCommunicationError
|
|
|
|
def to_s
|
|
"The address is already in use or unavailable: #{addr_to_s}."
|
|
end
|
|
end
|
|
|
|
|
|
###
|
|
#
|
|
# This exception is raised when an unsupported internet protocol is specified.
|
|
#
|
|
###
|
|
class UnsupportedProtocol < ::ArgumentError
|
|
include SocketError
|
|
|
|
def initialize(proto = nil)
|
|
self.proto = proto
|
|
end
|
|
|
|
def to_s
|
|
"The protocol #{proto} is not supported."
|
|
end
|
|
|
|
attr_accessor :proto
|
|
end
|
|
|
|
|
|
###
|
|
#
|
|
# This exception is raised when a proxy fails to pass a connection
|
|
#
|
|
###
|
|
class ConnectionProxyError < ConnectionError
|
|
def initialize(host,port,ptype,reason)
|
|
super(host,port)
|
|
self.ptype = ptype
|
|
self.reason = reason
|
|
end
|
|
|
|
def to_s
|
|
self.ptype + ": " + self.reason
|
|
end
|
|
|
|
attr_accessor :ptype, :reason
|
|
end
|
|
|
|
end
|
|
|