Included Modules

Class/Module Index [+]

Quicksearch

Rex::Socket::SslTcp

This class provides methods for interacting with an SSL TCP client connection.

Public Class Methods

create(hash = {}) click to toggle source

Creates an SSL TCP instance.

# File lib/rex/socket/ssl_tcp.rb, line 33
def self.create(hash = {})
        raise RuntimeError, "No OpenSSL support" if not @@loaded_openssl
        hash['SSL'] = true
        self.create_param(Rex::Socket::Parameters.from_hash(hash))
end
create_param(param) click to toggle source

Set the SSL flag to true and call the base class's create_param routine.

# File lib/rex/socket/ssl_tcp.rb, line 42
def self.create_param(param)
        param.ssl   = true
        Rex::Socket::Tcp.create_param(param)
end

Public Instance Methods

allow_nonblock?() click to toggle source

This flag determines whether to use the non-blocking openssl API calls when they are available. This is still buggy on Linux/Mac OS X, but is required on Windows

# File lib/rex/socket/ssl_tcp.rb, line 314
def allow_nonblock?
        avail = self.sslsock.respond_to?(:accept_nonblock)
        if avail and Rex::Compat.is_windows
                return true
        end
        false
end
cipher() click to toggle source

Access to the current cipher

# File lib/rex/socket/ssl_tcp.rb, line 291
def cipher
        sslsock.cipher if sslsock
end
close() click to toggle source

Closes the SSL socket.

# File lib/rex/socket/ssl_tcp.rb, line 261
def close
        sslsock.close rescue nil
        super
end
initsock(params = nil) click to toggle source

Initializes the SSL socket.

# File lib/rex/socket/ssl_tcp.rb, line 56
def initsock(params = nil)
        super

        version = :SSLv3
        if(params)
                case params.ssl_version
                when 'SSL2'
                        version = :SSLv2
                when 'SSL23'
                        version = :SSLv23
                when 'TLS1'
                        version = :TLSv1
                end
        end

        # Build the SSL connection
        self.sslctx  = OpenSSL::SSL::SSLContext.new(version)

        # Configure the SSL context
        # TODO: Allow the user to specify the verify mode and callback
        # Valid modes:
        #  VERIFY_CLIENT_ONCE
        #  VERIFY_FAIL_IF_NO_PEER_CERT
        #  VERIFY_NONE
        #  VERIFY_PEER
        self.sslctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
        self.sslctx.options = OpenSSL::SSL::OP_ALL

        # Set the verification callback
        self.sslctx.verify_callback = Proc.new do |valid, store|
                self.peer_verified = valid
                true
        end

        # Tie the context to a socket
        self.sslsock = OpenSSL::SSL::SSLSocket.new(self, self.sslctx)

        # XXX - enabling this causes infinite recursion, so disable for now
        # self.sslsock.sync_close = true


        # Force a negotiation timeout
        begin
        Timeout.timeout(params.timeout) do
                if not allow_nonblock?
                        self.sslsock.connect
                else
                        begin
                                self.sslsock.connect_nonblock

                        # Ruby 1.8.7 and 1.9.0/1.9.1 uses a standard Errno
                        rescue ::Errno::EAGAIN, ::Errno::EWOULDBLOCK
                                        IO::select(nil, nil, nil, 0.10)
                                        retry

                        # Ruby 1.9.2+ uses IO::WaitReadable/IO::WaitWritable
                        rescue ::Exception => e
                                if ::IO.const_defined?('WaitReadable') and e.kind_of?(::IO::WaitReadable)
                                        IO::select( [ self.sslsock ], nil, nil, 0.10 )
                                        retry
                                end

                                if ::IO.const_defined?('WaitWritable') and e.kind_of?(::IO::WaitWritable)
                                        IO::select( nil, [ self.sslsock ], nil, 0.10 )
                                        retry
                                end

                                raise e
                        end
                end
        end

        rescue ::Timeout::Error
                raise Rex::ConnectionTimeout.new(params.peerhost, params.peerport)
        end
end
peer_cert() click to toggle source

Access to peer cert

# File lib/rex/socket/ssl_tcp.rb, line 277
def peer_cert
        sslsock.peer_cert if sslsock
end
peer_cert_chain() click to toggle source

Access to peer cert chain

# File lib/rex/socket/ssl_tcp.rb, line 284
def peer_cert_chain
        sslsock.peer_cert_chain if sslsock
end
read(length = nil, opts = {}) click to toggle source

Reads data from the SSL socket.

# File lib/rex/socket/ssl_tcp.rb, line 202
def read(length = nil, opts = {})
        if not allow_nonblock?
                length = 16384 unless length
                begin
                        return sslsock.sysread(length)
                rescue ::IOError, ::Errno::EPIPE, ::OpenSSL::SSL::SSLError
                        return nil
                end
                return
        end


        begin
                while true
                        s = Rex::ThreadSafe.select( [ self.sslsock ], nil, nil, 0.10 )
                        if( s == nil || s[0] == nil )
                                next
                        end
                        return sslsock.read_nonblock( length )
                end

        rescue ::IOError, ::Errno::EPIPE
                return nil

        # Ruby 1.8.7 and 1.9.0/1.9.1 uses a standard Errno
        rescue ::Errno::EAGAIN, ::Errno::EWOULDBLOCK
                # Sleep for a tenth a second, or until we can read again
                Rex::ThreadSafe.select( [ self.sslsock ], nil, nil, 0.10 )
                # Decrement the block size to handle full sendQs better
                block_size = 1024
                # Try to write the data again
                retry

        # Ruby 1.9.2+ uses IO::WaitReadable/IO::WaitWritable
        rescue ::Exception => e
                if ::IO.const_defined?('WaitReadable') and e.kind_of?(::IO::WaitReadable)
                        IO::select( [ self.sslsock ], nil, nil, 0.5 )
                        retry
                end

                if ::IO.const_defined?('WaitWritable') and e.kind_of?(::IO::WaitWritable)
                        IO::select( nil, [ self.sslsock ], nil, 0.5 )
                        retry
                end

                # Another form of SSL error, this is always fatal
                if e.kind_of?(::OpenSSL::SSL::SSLError)
                        return nil
                end

                raise e
        end

end
shutdown(how=0) click to toggle source

Ignore shutdown requests

# File lib/rex/socket/ssl_tcp.rb, line 269
def shutdown(how=0)
        # Calling shutdown() on an SSL socket can lead to bad things
        # Cause of http://metasploit.com/dev/trac/ticket/102
end
sysread(*args) click to toggle source

Prevent a sysread from the bare socket

# File lib/rex/socket/ssl_tcp.rb, line 298
def sysread(*args)
        raise RuntimeError, "Invalid sysread() call on SSL socket"
end
syswrite(*args) click to toggle source

Prevent a sysread from the bare socket

# File lib/rex/socket/ssl_tcp.rb, line 305
def syswrite(*args)
        raise RuntimeError, "Invalid syswrite() call on SSL socket"
end
type?() click to toggle source
# File lib/rex/socket/ssl_tcp.rb, line 333
def type?
        return 'tcp-ssl'
end
write(buf, opts = {}) click to toggle source

Writes data over the SSL socket.

# File lib/rex/socket/ssl_tcp.rb, line 142
def write(buf, opts = {})
        return sslsock.write(buf) if not allow_nonblock?

        total_sent   = 0
        total_length = buf.length
        block_size   = 16384
        retry_time   = 0.5

        begin
                while( total_sent < total_length )
                        s = Rex::ThreadSafe.select( nil, [ self.sslsock ], nil, 0.25 )
                        if( s == nil || s[0] == nil )
                                next
                        end
                        data = buf[total_sent, block_size]
                        sent = sslsock.write_nonblock( data )
                        if sent > 0
                                total_sent += sent
                        end
                end

        rescue ::IOError, ::Errno::EPIPE
                return nil

        # Ruby 1.8.7 and 1.9.0/1.9.1 uses a standard Errno
        rescue ::Errno::EAGAIN, ::Errno::EWOULDBLOCK
                # Sleep for a half a second, or until we can write again
                Rex::ThreadSafe.select( nil, [ self.sslsock ], nil, retry_time )
                # Decrement the block size to handle full sendQs better
                block_size = 1024
                # Try to write the data again
                retry

        # Ruby 1.9.2+ uses IO::WaitReadable/IO::WaitWritable
        rescue ::Exception => e
                if ::IO.const_defined?('WaitReadable') and e.kind_of?(::IO::WaitReadable)
                        IO::select( [ self.sslsock ], nil, nil, retry_time )
                        retry
                end

                if ::IO.const_defined?('WaitWritable') and e.kind_of?(::IO::WaitWritable)
                        IO::select( nil, [ self.sslsock ], nil, retry_time )
                        retry
                end

                # Another form of SSL error, this is always fatal
                if e.kind_of?(::OpenSSL::SSL::SSLError)
                        return nil
                end

                # Bubble the event up to the caller otherwise
                raise e
        end

        total_sent
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.