Class: Puma::MiniSSL::Engine
Relationships & Source Files | |
Inherits: | Object |
Defined in: | ext/puma_http11/mini_ssl.c |
Class Method Summary
Instance Attribute Summary
- #init? ⇒ Boolean readonly
Instance Method Summary
Class Method Details
.client
[ GitHub ]# File 'ext/puma_http11/mini_ssl.c', line 297
VALUE engine_init_client(VALUE klass) { VALUE obj; ms_conn* conn = engine_alloc(klass, &obj); #ifdef HAVE_DTLS_METHOD conn->ctx = SSL_CTX_new(DTLS_method()); #else conn->ctx = SSL_CTX_new(DTLSv1_method()); #endif conn->ssl = SSL_new(conn->ctx); SSL_set_app_data(conn->ssl, NULL); SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL); SSL_set_bio(conn->ssl, conn->read, conn->write); SSL_set_connect_state(conn->ssl); return obj; }
.server(mini_ssl_ctx)
[ GitHub ]# File 'ext/puma_http11/mini_ssl.c', line 162
VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) { VALUE obj, session_id_bytes; SSL_CTX* ctx; SSL* ssl; int min, ssl_options; ms_conn* conn = engine_alloc(self, &obj); ID sym_key = rb_intern("key"); VALUE key = rb_funcall(mini_ssl_ctx, sym_key, 0); StringValue(key); ID sym_cert = rb_intern("cert"); VALUE cert = rb_funcall(mini_ssl_ctx, sym_cert, 0); StringValue(cert); ID sym_ca = rb_intern("ca"); VALUE ca = rb_funcall(mini_ssl_ctx, sym_ca, 0); ID sym_verify_mode = rb_intern("verify_mode"); VALUE verify_mode = rb_funcall(mini_ssl_ctx, sym_verify_mode, 0); ID sym_ssl_cipher_filter = rb_intern("ssl_cipher_filter"); VALUE ssl_cipher_filter = rb_funcall(mini_ssl_ctx, sym_ssl_cipher_filter, 0); ID sym_no_tlsv1 = rb_intern("no_tlsv1"); VALUE no_tlsv1 = rb_funcall(mini_ssl_ctx, sym_no_tlsv1, 0); ID sym_no_tlsv1_1 = rb_intern("no_tlsv1_1"); VALUE no_tlsv1_1 = rb_funcall(mini_ssl_ctx, sym_no_tlsv1_1, 0); #ifdef HAVE_TLS_SERVER_METHOD ctx = SSL_CTX_new(TLS_server_method()); #else ctx = SSL_CTX_new(SSLv23_server_method()); #endif conn->ctx = ctx; SSL_CTX_use_certificate_chain_file(ctx, RSTRING_PTR(cert)); SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM); if (!NIL_P(ca)) { StringValue(ca); SSL_CTX_load_verify_locations(ctx, RSTRING_PTR(ca), NULL); } ssl_options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_COMPRESSION; #ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION if (RTEST(no_tlsv1_1)) { min = TLS1_2_VERSION; } else if (RTEST(no_tlsv1)) { min = TLS1_1_VERSION; } else { min = TLS1_VERSION; } SSL_CTX_set_min_proto_version(ctx, min); SSL_CTX_set_options(ctx, ssl_options); #else /* As of 1.0.2f, SSL_OP_SINGLE_DH_USE key use is always on */ ssl_options |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE; if (RTEST(no_tlsv1)) { ssl_options |= SSL_OP_NO_TLSv1; } if(RTEST(no_tlsv1_1)) { ssl_options |= SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1; } SSL_CTX_set_options(ctx, ssl_options); #endif SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); if (!NIL_P(ssl_cipher_filter)) { StringValue(ssl_cipher_filter); SSL_CTX_set_cipher_list(ctx, RSTRING_PTR(ssl_cipher_filter)); } else { SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL@STRENGTH"); } // Random.bytes available in Ruby 2.5 and later, Random::DEFAULT deprecated in 3.0 session_id_bytes = rb_funcall( #ifdef HAVE_RANDOM_BYTES rb_cRandom, #else rb_const_get(rb_cRandom, rb_intern_const("DEFAULT")), #endif rb_intern_const("bytes"), 1, ULL2NUM(SSL_MAX_SSL_SESSION_ID_LENGTH)); SSL_CTX_set_session_id_context(ctx, (unsigned char *) RSTRING_PTR(session_id_bytes), SSL_MAX_SSL_SESSION_ID_LENGTH); DH *dh = get_dh2048(); SSL_CTX_set_tmp_dh(ctx, dh); #if OPENSSL_VERSION_NUMBER < 0x10002000L // Remove this case if OpenSSL 1.0.1 (now EOL) support is no // longer needed. EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); if (ecdh) { SSL_CTX_set_tmp_ecdh(ctx, ecdh); EC_KEY_free(ecdh); } #elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) // Prior to OpenSSL 1.1.0, servers must manually enable server-side ECDH // negotiation. SSL_CTX_set_ecdh_auto(ctx, 1); #endif ssl = SSL_new(ctx); conn->ssl = ssl; SSL_set_app_data(ssl, NULL); if (NIL_P(verify_mode)) { /* SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); */ } else { SSL_set_verify(ssl, NUM2INT(verify_mode), engine_verify_callback); } SSL_set_bio(ssl, conn->read, conn->write); SSL_set_accept_state(ssl); return obj; }
Instance Attribute Details
#init? ⇒ Boolean
(readonly)
[ GitHub ]
# File 'ext/puma_http11/mini_ssl.c', line 453
VALUE engine_init(VALUE self) { ms_conn* conn; Data_Get_Struct(self, ms_conn, conn); return SSL_in_init(conn->ssl) ? Qtrue : Qfalse; }
Instance Method Details
#extract
[ GitHub ]# File 'ext/puma_http11/mini_ssl.c', line 416
VALUE engine_extract(VALUE self) { ms_conn* conn; int bytes; size_t pending; char buf[512]; Data_Get_Struct(self, ms_conn, conn); pending = BIO_pending(conn->write); if(pending > 0) { bytes = BIO_read(conn->write, buf, sizeof(buf)); if(bytes > 0) { return rb_str_new(buf, bytes); } else if(!BIO_should_retry(conn->write)) { raise_error(conn->ssl, bytes); } } return Qnil; }
#inject(str)
[ GitHub ]# File 'ext/puma_http11/mini_ssl.c', line 315
VALUE engine_inject(VALUE self, VALUE str) { ms_conn* conn; long used; Data_Get_Struct(self, ms_conn, conn); StringValue(str); used = BIO_write(conn->read, RSTRING_PTR(str), (int)RSTRING_LEN(str)); if(used == 0 || used == -1) { return Qfalse; } return INT2FIX(used); }
#peercert
[ GitHub ]# File 'ext/puma_http11/mini_ssl.c', line 461
VALUE engine_peercert(VALUE self) { ms_conn* conn; X509* cert; int bytes; unsigned char* buf = NULL; ms_cert_buf* cert_buf = NULL; VALUE rb_cert_buf; Data_Get_Struct(self, ms_conn, conn); cert = SSL_get_peer_certificate(conn->ssl); if(!cert) { /* * See if there was a failed certificate associated with this client. */ cert_buf = (ms_cert_buf*)SSL_get_app_data(conn->ssl); if(!cert_buf) { return Qnil; } buf = cert_buf->buf; bytes = cert_buf->bytes; } else { bytes = i2d_X509(cert, &buf); X509_free(cert); if(bytes < 0) { return Qnil; } } rb_cert_buf = rb_str_new((const char*)(buf), bytes); if(!cert_buf) { OPENSSL_free(buf); } return rb_cert_buf; }
#read
[ GitHub ]# File 'ext/puma_http11/mini_ssl.c', line 366
VALUE engine_read(VALUE self) { ms_conn* conn; char buf[512]; int bytes, error; Data_Get_Struct(self, ms_conn, conn); ERR_clear_error(); bytes = SSL_read(conn->ssl, (void*)buf, sizeof(buf)); if(bytes > 0) { return rb_str_new(buf, bytes); } if(SSL_want_read(conn->ssl)) return Qnil; error = SSL_get_error(conn->ssl, bytes); if(error == SSL_ERROR_ZERO_RETURN) { rb_eof_error(); } else { raise_error(conn->ssl, bytes); } return Qnil; }
#shutdown
[ GitHub ]# File 'ext/puma_http11/mini_ssl.c', line 437
VALUE engine_shutdown(VALUE self) { ms_conn* conn; int ok; Data_Get_Struct(self, ms_conn, conn); ERR_clear_error(); ok = SSL_shutdown(conn->ssl); if (ok == 0) { return Qfalse; } return Qtrue; }
#write(str)
[ GitHub ]# File 'ext/puma_http11/mini_ssl.c', line 394
VALUE engine_write(VALUE self, VALUE str) { ms_conn* conn; int bytes; Data_Get_Struct(self, ms_conn, conn); StringValue(str); ERR_clear_error(); bytes = SSL_write(conn->ssl, (void*)RSTRING_PTR(str), (int)RSTRING_LEN(str)); if(bytes > 0) { return INT2FIX(bytes); } if(SSL_want_write(conn->ssl)) return Qnil; raise_error(conn->ssl, bytes); return Qnil; }