Class: RubyTls::SSL::Context

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby-tls/ssl.rb

Constant Summary collapse

CIPHERS =
'EECDH+AESGCM:EDH+AESGCM:ECDHE-RSA-AES128-GCM-SHA256:AES256+EECDH:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4'
SESSION =
'ruby-tls'
ALPN_LOOKUP =
::Concurrent::Map.new
ALPN_Select_CB =
FFI::Function.new(:int, [
    # array of str, unit8 out,uint8 in,        *arg
    :pointer, :pointer, :pointer, :string, :uint, :pointer
]) do |ssl_p, out, outlen, inp, inlen, arg|
    ssl = Box::InstanceLookup[ssl_p.address]
    return SSL::SSL_TLSEXT_ERR_ALERT_FATAL unless ssl

    protos = ssl.context.alpn_str
    status = SSL.SSL_select_next_proto(out, outlen, protos, protos.length, inp, inlen)
    ssl.negotiated

    case status
    when SSL::OPENSSL_NPN_UNSUPPORTED
        SSL::SSL_TLSEXT_ERR_ALERT_FATAL
    when SSL::OPENSSL_NPN_NEGOTIATED
        SSL::SSL_TLSEXT_ERR_OK
    when SSL::OPENSSL_NPN_NO_OVERLAP
        SSL::SSL_TLSEXT_ERR_ALERT_WARNING
    end
end
ServerNameCB =
FFI::Function.new(:int, [:pointer, :pointer, :pointer]) do |ssl, _, _|
    ruby_ssl = Box::InstanceLookup[ssl.address]
    return SSL::SSL_TLSEXT_ERR_NOACK unless ruby_ssl

    ctx = ruby_ssl.hosts[SSL.SSL_get_servername(ssl, SSL::TLSEXT_NAMETYPE_host_name)]
    if ctx
        SSL.SSL_set_SSL_CTX(ssl, ctx.ssl_ctx)
        SSL::SSL_TLSEXT_ERR_OK
    else
        SSL::SSL_TLSEXT_ERR_ALERT_FATAL
    end
end

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(server, options = {}) ⇒ Context

Returns a new instance of Context.



341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
# File 'lib/ruby-tls/ssl.rb', line 341

def initialize(server, options = {})
    @is_server = server

    if @is_server
        @ssl_ctx = SSL.SSL_CTX_new(SSL.SSLv23_server_method)
        set_private_key(options[:private_key] || SSL::DEFAULT_PRIVATE)
        set_certificate(options[:cert_chain]  || SSL::DEFAULT_CERT)
        set_client_ca(options[:client_ca])
    else
        @ssl_ctx = SSL.SSL_CTX_new(SSL.SSLv23_client_method)
    end

    SSL.SSL_CTX_set_options(@ssl_ctx, SSL::SSL_OP_ALL)
    SSL.SSL_CTX_set_mode(@ssl_ctx, SSL::SSL_MODE_RELEASE_BUFFERS)

    SSL.SSL_CTX_set_cipher_list(@ssl_ctx, options[:ciphers] || CIPHERS)
    @alpn_set = false

    if @is_server
        SSL.SSL_CTX_sess_set_cache_size(@ssl_ctx, 128)
        SSL.SSL_CTX_set_session_id_context(@ssl_ctx, SESSION, 8)

        if SSL::ALPN_SUPPORTED && options[:protocols]
            @alpn_str = Context.build_alpn_string(options[:protocols])
            SSL.SSL_CTX_set_alpn_select_cb(@ssl_ctx, ALPN_Select_CB, nil)
            @alpn_set = true
        end
    else
        set_private_key(options[:private_key])
        set_certificate(options[:cert_chain])

        # Check for ALPN support
        if SSL::ALPN_SUPPORTED && options[:protocols]
            protocols = Context.build_alpn_string(options[:protocols])
            @alpn_set = SSL.SSL_CTX_set_alpn_protos(@ssl_ctx, protocols, protocols.length) == 0
        end
    end
end

Instance Attribute Details

#alpn_setObject (readonly)

Returns the value of attribute alpn_set.



389
390
391
# File 'lib/ruby-tls/ssl.rb', line 389

def alpn_set
  @alpn_set
end

#alpn_strObject (readonly)

Returns the value of attribute alpn_str.



390
391
392
# File 'lib/ruby-tls/ssl.rb', line 390

def alpn_str
  @alpn_str
end

#is_serverObject (readonly)

Returns the value of attribute is_server.



387
388
389
# File 'lib/ruby-tls/ssl.rb', line 387

def is_server
  @is_server
end

#ssl_ctxObject (readonly)

Returns the value of attribute ssl_ctx.



388
389
390
# File 'lib/ruby-tls/ssl.rb', line 388

def ssl_ctx
  @ssl_ctx
end

Instance Method Details

#add_server_name_indicationObject



392
393
394
395
# File 'lib/ruby-tls/ssl.rb', line 392

def add_server_name_indication
    raise 'only valid for server mode context' unless @is_server
    SSL.SSL_CTX_set_tlsext_servername_callback(@ssl_ctx, ServerNameCB)
end

#cleanupObject



380
381
382
383
384
385
# File 'lib/ruby-tls/ssl.rb', line 380

def cleanup
    if @ssl_ctx
        SSL.SSL_CTX_free(@ssl_ctx)
        @ssl_ctx = nil
    end
end