123456789_123456789_123456789_123456789_123456789_

Class: Puma::MiniSSL::Engine

Relationships & Source Files
Inherits: Object
Defined in: ext/puma_http11/mini_ssl.c

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Class Method Details

.client

[ GitHub ]

  
# File 'ext/puma_http11/mini_ssl.c', line 216

VALUE engine_init_client(VALUE klass) {
  VALUE obj;
  ms_conn* conn = engine_alloc(klass, &obj);

  conn->ctx = SSL_CTX_new(DTLSv1_method());
  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 141

VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
  VALUE obj;
  SSL_CTX* ctx;
  SSL* ssl;

  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);

  ctx = SSL_CTX_new(SSLv23_server_method());
  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_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_COMPRESSION);
  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");
  }

  DH *dh = get_dh1024();
  SSL_CTX_set_tmp_dh(ctx, dh);

#ifndef OPENSSL_NO_ECDH
  EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_secp521r1);
  if (ecdh) {
    SSL_CTX_set_tmp_ecdh(ctx, ecdh);
    EC_KEY_free(ecdh);
  }
#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 369

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 332

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 231

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 377

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 282

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 353

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 310

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;
}