class PacketThief::Handlers::AbstractSSLHandler

Parent class for both SSLServer and SSLClient.

TODO: get_peer_cert, get_peername, etc.

Attributes

ctx[RW]

The OpenSSL::SSL::SSLContext. Modify this in #post_init or in the initializing code block to add certificates, etc.

sni_hostname[RW]

(Used by SSLClient only) The hostname that the SNI TLS extension should request. Set it in #post_init or in the initializing code block — it is applied to the SSLSocket during tls_begin.

sslsocket[RW]

The SSLSocket. It is not available until tls_begin creates it, after #post_init and the initializing code block.

tcpsocket[RW]

The TCPSocket that the SSLSocket will be created from. It is added by initialize.

Public Class Methods

new(tcpsocket, logger=nil) click to toggle source
# File lib/packetthief/handlers/abstract_ssl_handler.rb, line 29
def initialize(tcpsocket, logger=nil)
  @logger = logger
  logdebug "initialize"
  # Set up initial values
  @tcpsocket = tcpsocket
  @ctx = OpenSSL::SSL::SSLContext.new

  @close_after_writing = false
  @state = :new
end

Public Instance Methods

close_connection() click to toggle source
# File lib/packetthief/handlers/abstract_ssl_handler.rb, line 193
      def close_connection
        detach
        @sslsocket.close if @sslsocket and not @sslsocket.closed?
        @tcpsocket.close if not @tcpsocket.closed?
#        unbind
      end
close_connection_after_writing() click to toggle source
# File lib/packetthief/handlers/abstract_ssl_handler.rb, line 200
def close_connection_after_writing
  @close_after_writing = true
  # if we aren't waiting to write, then we can flush and close.
  if not notify_writable?
    @sslsocket.flush
    close_connection
  end

end
notify_readable() click to toggle source

Calls accept_nonblock/connect_nonblock, read_nonblock, or write_nonblock based on the current state of the connection.

# File lib/packetthief/handlers/abstract_ssl_handler.rb, line 63
def notify_readable
  logdebug "notify_readable", :state => @state
  case @state
  when :initialized
    attempt_connection
  when :ready_to_read
    attempt_read
  when :write_needs_to_read
    attempt_write
  end
end
notify_writable() click to toggle source

We only care about #notify_writable if we are waiting to write for some reason.

# File lib/packetthief/handlers/abstract_ssl_handler.rb, line 77
def notify_writable
  logdebug "notify_writable", :state => @state
  notify_writable = false # disable it now. if we still need it, we'll renabled it.
  case @state
  when :initialized
    attempt_connection
  when :read_needs_to_write
    attempt_read
  when :write_needs_to_write
    attempt_write
  end

  # if we waiting to close and are not longer waiting to write, we can flush and close the connection.
  if @close_after_writing and not notify_writable?
    @sslsock.flush
    close_connection
  end
end
post_init() click to toggle source

Note that #post_init dos not have access to the sslsocket. The sslsocket is not added until #tls_begin is called, after the code block.

post_init gives you a chance to manipulate the SSLContext.

# File lib/packetthief/handlers/abstract_ssl_handler.rb, line 216
def post_init
end
receive_data(data) click to toggle source

Override this to do something with the unecrypted data.

# File lib/packetthief/handlers/abstract_ssl_handler.rb, line 236
def receive_data(data)
  logdebug "receive_data:", :data => data
end
send_data(data) click to toggle source

Call this to send data to the other end of the connection.

# File lib/packetthief/handlers/abstract_ssl_handler.rb, line 188
def send_data(data)
  logdebug "send_data:", :data => data
  attempt_write(data)
end
tls_begin() click to toggle source

Creates sslsocket from tcpsocket and ctx, and initializes the handler’s internal state. Called from the class method that creates the object, after #post_init and the optional code block.

@note (SSLClient only) If @#sni_hostname exists on the handler at this point, it will be added to the SSLSocket in order to enable sending a hostname in the SNI TLS extension.

# File lib/packetthief/handlers/abstract_ssl_handler.rb, line 47
def tls_begin
  logdebug "tls begin", :sni_hostname => @sni_hostname
  @sslsocket = OpenSSL::SSL::SSLSocket.new(@tcpsocket, @ctx)
  if @sni_hostname
    if @sslsocket.respond_to? :hostname
      @sslsocket.hostname = @sni_hostname
    else
      logwarn "#{@sslsocket.class} does not support setting an SNI hostname! This requires Ruby 1.9.x built against OpenSSL with SNI support.",
        :ruby_version => RUBY_VERSION
    end
  end
  @state = :initialized
end
tls_failed_handshake(e) click to toggle source

Called right after accept_nonblock fails for some unknown reason. The only parameter contains the OpenSSL::SSL::SSLError object that was thrown.

The connection will be closed after this.

# File lib/packetthief/handlers/abstract_ssl_handler.rb, line 231
def tls_failed_handshake(e)
  logerror "tls_failed_handshake: Failed to accept: #{e} (#{e.class})"
end
tls_successful_handshake() click to toggle source

Called right after the SSL handshake succeeds. This is your “new” post_init.

# File lib/packetthief/handlers/abstract_ssl_handler.rb, line 222
def tls_successful_handshake
  logdebug "Succesful handshake!"
end
unbind() click to toggle source

Override this to do something when the socket is finished.

# File lib/packetthief/handlers/abstract_ssl_handler.rb, line 241
def unbind
  logdebug "unbind"
end
write_buffer() click to toggle source
# File lib/packetthief/handlers/abstract_ssl_handler.rb, line 143
def write_buffer
  @write_buffer ||= ""
end
write_buffer=(rhs) click to toggle source
# File lib/packetthief/handlers/abstract_ssl_handler.rb, line 148
def write_buffer=(rhs)
  @write_buffer = rhs
end