Class: PacketThief::Handlers::AbstractSSLHandler

Inherits:
EM::Connection
  • Object
show all
Includes:
Logging
Defined in:
lib/packetthief/handlers/abstract_ssl_handler.rb

Overview

Parent class for both SSLServer and SSLClient.

TODO: get_peer_cert, get_peername, etc.

Direct Known Subclasses

SSLClient, SSLServer

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Logging

log

Constructor Details

#initialize(tcpsocket) ⇒ AbstractSSLHandler

Returns a new instance of AbstractSSLHandler.



29
30
31
32
33
34
35
36
37
# File 'lib/packetthief/handlers/abstract_ssl_handler.rb', line 29

def initialize(tcpsocket)
  logdebug "initialize"
  # Set up initial values
  @tcpsocket = tcpsocket
  @ctx = OpenSSL::SSL::SSLContext.new

  @close_after_writing = false
  @state = :new
end

Instance Attribute Details

#ctxObject

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



14
15
16
# File 'lib/packetthief/handlers/abstract_ssl_handler.rb', line 14

def ctx
  @ctx
end

#sni_hostnameObject

(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.



27
28
29
# File 'lib/packetthief/handlers/abstract_ssl_handler.rb', line 27

def sni_hostname
  @sni_hostname
end

#sslsocketObject

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



22
23
24
# File 'lib/packetthief/handlers/abstract_ssl_handler.rb', line 22

def sslsocket
  @sslsocket
end

#tcpsocketObject

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



18
19
20
# File 'lib/packetthief/handlers/abstract_ssl_handler.rb', line 18

def tcpsocket
  @tcpsocket
end

Instance Method Details

#close_connectionObject



192
193
194
195
196
197
# File 'lib/packetthief/handlers/abstract_ssl_handler.rb', line 192

def close_connection
  detach
  @sslsocket.close if @sslsocket and not @sslsocket.closed?
  @tcpsocket.close if not @tcpsocket.closed?
#        unbind
end

#close_connection_after_writingObject



199
200
201
202
203
204
205
206
207
# File 'lib/packetthief/handlers/abstract_ssl_handler.rb', line 199

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_readableObject

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



62
63
64
65
66
67
68
69
70
71
72
# File 'lib/packetthief/handlers/abstract_ssl_handler.rb', line 62

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_writableObject

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



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/packetthief/handlers/abstract_ssl_handler.rb', line 76

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_initObject

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.



215
216
# File 'lib/packetthief/handlers/abstract_ssl_handler.rb', line 215

def post_init
end

#receive_data(data) ⇒ Object

Override this to do something with the unecrypted data.



235
236
237
# File 'lib/packetthief/handlers/abstract_ssl_handler.rb', line 235

def receive_data(data)
  logdebug "receive_data:", :data => data
end

#send_data(data) ⇒ Object

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



187
188
189
190
# File 'lib/packetthief/handlers/abstract_ssl_handler.rb', line 187

def send_data(data)
  logdebug "send_data:", :data => data
  attempt_write(data)
end

#tls_beginObject

Note:

(SSLClient only) If @sni_hostname exists on the handler at this

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.

point, it will be added to the SSLSocket in order to enable sending a hostname in the SNI TLS extension.



46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/packetthief/handlers/abstract_ssl_handler.rb', line 46

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) ⇒ Object

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.



230
231
232
# File 'lib/packetthief/handlers/abstract_ssl_handler.rb', line 230

def tls_failed_handshake(e)
  logerror "tls_failed_handshake: Failed to accept: #{e} (#{e.class})"
end

#tls_successful_handshakeObject

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



221
222
223
# File 'lib/packetthief/handlers/abstract_ssl_handler.rb', line 221

def tls_successful_handshake
  logdebug "Succesful handshake!"
end

#unbindObject

Override this to do something when the socket is finished.



240
241
242
# File 'lib/packetthief/handlers/abstract_ssl_handler.rb', line 240

def unbind
  logdebug "unbind"
end

#write_bufferObject



142
143
144
# File 'lib/packetthief/handlers/abstract_ssl_handler.rb', line 142

def write_buffer
  @write_buffer ||= ""
end

#write_buffer=(rhs) ⇒ Object



147
148
149
# File 'lib/packetthief/handlers/abstract_ssl_handler.rb', line 147

def write_buffer=(rhs)
  @write_buffer = rhs
end