class Arachni::HTTP::ProxyServer::SSLInterceptor

Constants

CA_CERTIFICATE
CA_KEY
CA_PASSPHRASE

Public Class Methods

new( options ) click to toggle source
# File lib/arachni/http/proxy_server/ssl_interceptor.rb, line 23
def initialize( options )
    super

    @origin_host = options[:origin_host]
end

Public Instance Methods

on_close( reason = nil ) click to toggle source
# File lib/arachni/http/proxy_server/ssl_interceptor.rb, line 34
def on_close( reason = nil )
    print_debug_level_3 "Closed because: [#{reason.class}] #{reason}"
    @parent.mark_connection_inactive self
end
on_connect() click to toggle source
# File lib/arachni/http/proxy_server/ssl_interceptor.rb, line 29
def on_connect
    print_debug_level_3 'Connected, starting SSL handshake.'
    start_tls
end
start_tls() click to toggle source
# File lib/arachni/http/proxy_server/ssl_interceptor.rb, line 39
def start_tls
    if @socket.is_a? OpenSSL::SSL::SSLSocket
        @ssl_context = @socket.context
        return
    end

    if @role == :server
        ca     = OpenSSL::X509::Certificate.new( File.read( CA_CERTIFICATE ) )
        ca_key = OpenSSL::PKey::RSA.new( File.read( CA_KEY ), CA_PASSPHRASE )

        keypair = OpenSSL::PKey::RSA.new( 2048 )

        req            = OpenSSL::X509::Request.new
        req.version    = 0
        req.subject    = OpenSSL::X509::Name.parse(
            "CN=#{@origin_host}/subjectAltName=#{@origin_host}/O=Arachni/OU=Proxy/L=Athens/ST=Attika/C=GR"
        )
        req.public_key = keypair.public_key
        req.sign( keypair, OpenSSL::Digest::SHA256.new )

        cert            = OpenSSL::X509::Certificate.new
        cert.version    = 2
        cert.serial     = rand( 999999 )
        cert.not_before = Time.new - 600
        cert.not_after  = cert.not_before + (60 * 60 * 24 * 365)
        cert.public_key = req.public_key
        cert.subject    = req.subject
        cert.issuer     = ca.subject

        ef = OpenSSL::X509::ExtensionFactory.new
        ef.subject_certificate = cert
        ef.issuer_certificate  = ca

        cert.extensions = [
            ef.create_extension( 'basicConstraints', 'CA:FALSE', true ),
            ef.create_extension( 'extendedKeyUsage', 'serverAuth', false ),
            ef.create_extension( 'subjectKeyIdentifier', 'hash' ),
            ef.create_extension( 'authorityKeyIdentifier', 'keyid:always,issuer:always' ),
            ef.create_extension( 'keyUsage',
                                 'nonRepudiation,digitalSignature,keyEncipherment,dataEncipherment',
                                 true
            )
        ]
        cert.sign( ca_key, OpenSSL::Digest::SHA256.new )

        @ssl_context = OpenSSL::SSL::SSLContext.new
        @ssl_context.cert = cert
        @ssl_context.key  = keypair

        @socket = OpenSSL::SSL::SSLServer.new( @socket, @ssl_context )
    else
        @socket = OpenSSL::SSL::SSLSocket.new( @socket, @ssl_context )
        @socket.sync_close = true

        # We've switched to SSL, a connection needs to be re-established
        # via the SSL handshake.
        @connected         = false
    end

    @socket
end