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
- #extract
- #inject(str)
-
#peercert ⇒ String?
Returns
nilwhen Context#verify_mode is set to VERIFY_NONE. - #read
- #shutdown
- #ssl_vers_st
- #write(str)
Class Method Details
.client
[ GitHub ]# File 'ext/puma_http11/mini_ssl.c', line 515
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(sslctx)
[ GitHub ]# File 'ext/puma_http11/mini_ssl.c', line 497
VALUE engine_init_server(VALUE self, VALUE sslctx) {
ms_conn* conn;
VALUE obj;
SSL_CTX* ctx;
SSL* ssl;
conn = engine_alloc(self, &obj);
TypedData_Get_Struct(sslctx, SSL_CTX, &sslctx_type, ctx);
ssl = SSL_new(ctx);
conn->ssl = ssl;
SSL_set_app_data(ssl, NULL);
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 688
VALUE engine_init(VALUE self) {
ms_conn* conn;
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
return SSL_in_init(conn->ssl) ? Qtrue : Qfalse;
}
Instance Method Details
#extract
[ GitHub ]# File 'ext/puma_http11/mini_ssl.c', line 634
VALUE engine_extract(VALUE self) {
ms_conn* conn;
int bytes;
size_t pending;
// https://www.openssl.org/docs/manmaster/man3/BIO_f_buffer.html
// crypto/bio/bf_buff.c DEFAULT_BUFFER_SIZE
char buf[4096];
TypedData_Get_Struct(self, ms_conn, &engine_data_type, 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 533
VALUE engine_inject(VALUE self, VALUE str) {
ms_conn* conn;
long used;
TypedData_Get_Struct(self, ms_conn, &engine_data_type, 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 ⇒ String?
Returns nil when Context#verify_mode is set to VERIFY_NONE.
# File 'ext/puma_http11/mini_ssl.c', line 696
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;
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
cert = SSL_get1_peer_certificate(conn->ssl);
#else
cert = SSL_get_peer_certificate(conn->ssl);
#endif
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 584
VALUE engine_read(VALUE self) {
ms_conn* conn;
char buf[512];
int bytes, error;
TypedData_Get_Struct(self, ms_conn, &engine_data_type, 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 657
VALUE engine_shutdown(VALUE self) {
ms_conn* conn;
int ok;
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
if (SSL_in_init(conn->ssl)) {
// Avoid "shutdown while in init" error
// See https://github.com/openssl/openssl/blob/openssl-3.5.2/ssl/ssl_lib.c#L2827-L2828
return Qtrue;
}
ERR_clear_error();
ok = SSL_shutdown(conn->ssl);
// See https://github.com/openssl/openssl/blob/openssl-3.5.2/ssl/ssl_lib.c#L2792-L2797
// for description of SSL_shutdown return values.
switch (ok) {
case 0:
// "close notify" alert is sent by us.
return Qfalse;
case 1:
// "close notify" alert was received from peer.
return Qtrue;
default:
raise_error(conn->ssl, ok);
}
return Qnil;
}
#ssl_vers_st
# File 'ext/puma_http11/mini_ssl.c', line 742
static VALUE
engine_ssl_vers_st(VALUE self) {
ms_conn* conn;
TypedData_Get_Struct(self, ms_conn, &engine_data_type, conn);
return rb_ary_new3(2, rb_str_new2(SSL_get_version(conn->ssl)), rb_str_new2(SSL_state_string(conn->ssl)));
}
#write(str)
[ GitHub ]# File 'ext/puma_http11/mini_ssl.c', line 612
VALUE engine_write(VALUE self, VALUE str) {
ms_conn* conn;
int bytes;
TypedData_Get_Struct(self, ms_conn, &engine_data_type, 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;
}