static VALUE ossl_ssl_setup(VALUE self) { VALUE io, v_ctx, cb; SSL_CTX *ctx; SSL *ssl; rb_io_t *fptr; Data_Get_Struct(self, SSL, ssl); if(!ssl){ v_ctx = ossl_ssl_get_ctx(self); Data_Get_Struct(v_ctx, SSL_CTX, ctx); ssl = SSL_new(ctx); if (!ssl) { ossl_raise(eSSLError, "SSL_new:"); } DATA_PTR(self) = ssl; io = ossl_ssl_get_io(self); GetOpenFile(io, fptr); rb_io_check_readable(fptr); rb_io_check_writable(fptr); SSL_set_fd(ssl, TO_SOCKET(FPTR_TO_FD(fptr))); SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void*)self); cb = ossl_sslctx_get_verify_cb(v_ctx); SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void*)cb); cb = ossl_sslctx_get_client_cert_cb(v_ctx); SSL_set_ex_data(ssl, ossl_ssl_ex_client_cert_cb_idx, (void*)cb); cb = ossl_sslctx_get_tmp_dh_cb(v_ctx); SSL_set_ex_data(ssl, ossl_ssl_ex_tmp_dh_callback_idx, (void*)cb); } return Qtrue; }
static VALUE ossl_ssl_setup(VALUE self) { VALUE io, v_ctx, cb; SSL_CTX *ctx; SSL *ssl; rb_io_t *fptr; Data_Get_Struct(self, SSL, ssl); if(!ssl){ #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME VALUE hostname = rb_iv_get(self, "@hostname"); #endif v_ctx = ossl_ssl_get_ctx(self); Data_Get_Struct(v_ctx, SSL_CTX, ctx); ssl = SSL_new(ctx); if (!ssl) { ossl_raise(eSSLError, "SSL_new:"); } DATA_PTR(self) = ssl; #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME if (!NIL_P(hostname)) { if (SSL_set_tlsext_host_name(ssl, StringValuePtr(hostname)) != 1) ossl_raise(eSSLError, "SSL_set_tlsext_host_name:"); } #endif io = ossl_ssl_get_io(self); GetOpenFile(io, fptr); rb_io_check_readable(fptr); rb_io_check_writable(fptr); SSL_set_fd(ssl, TO_SOCKET(FPTR_TO_FD(fptr))); SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void*)self); cb = ossl_sslctx_get_verify_cb(v_ctx); SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void*)cb); cb = ossl_sslctx_get_client_cert_cb(v_ctx); SSL_set_ex_data(ssl, ossl_ssl_ex_client_cert_cb_idx, (void*)cb); cb = ossl_sslctx_get_tmp_dh_cb(v_ctx); SSL_set_ex_data(ssl, ossl_ssl_ex_tmp_dh_callback_idx, (void*)cb); } return Qtrue; }
/* * call-seq: * ctx.setup => Qtrue # first time * ctx.setup => nil # thereafter * * This method is called automatically when a new SSLSocket is created. * Normally you do not need to call this method (unless you are writing an extension in C). */ static VALUE ossl_sslctx_setup(VALUE self) { SSL_CTX *ctx; X509 *cert = NULL, *client_ca = NULL; X509_STORE *store; EVP_PKEY *key = NULL; char *ca_path = NULL, *ca_file = NULL; int i, verify_mode; VALUE val; if(OBJ_FROZEN(self)) return Qnil; Data_Get_Struct(self, SSL_CTX, ctx); #if !defined(OPENSSL_NO_DH) if (RTEST(ossl_sslctx_get_tmp_dh_cb(self))){ SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback); } else{ SSL_CTX_set_tmp_dh_callback(ctx, ossl_default_tmp_dh_callback); } #endif SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_ptr_idx, (void*)self); val = ossl_sslctx_get_cert_store(self); if(!NIL_P(val)){ /* * WORKAROUND: * X509_STORE can count references, but * X509_STORE_free() doesn't care it. * So we won't increment it but mark it by ex_data. */ store = GetX509StorePtr(val); /* NO NEED TO DUP */ SSL_CTX_set_cert_store(ctx, store); SSL_CTX_set_ex_data(ctx, ossl_ssl_ex_store_p, (void*)1); } val = ossl_sslctx_get_extra_cert(self); if(!NIL_P(val)){ rb_block_call(val, rb_intern("each"), 0, 0, ossl_sslctx_add_extra_chain_cert_i, self); } /* private key may be bundled in certificate file. */ val = ossl_sslctx_get_cert(self); cert = NIL_P(val) ? NULL : GetX509CertPtr(val); /* NO DUP NEEDED */ val = ossl_sslctx_get_key(self); key = NIL_P(val) ? NULL : GetPKeyPtr(val); /* NO DUP NEEDED */ if (cert && key) { if (!SSL_CTX_use_certificate(ctx, cert)) { /* Adds a ref => Safe to FREE */ ossl_raise(eSSLError, "SSL_CTX_use_certificate:"); } if (!SSL_CTX_use_PrivateKey(ctx, key)) { /* Adds a ref => Safe to FREE */ ossl_raise(eSSLError, "SSL_CTX_use_PrivateKey:"); } if (!SSL_CTX_check_private_key(ctx)) { ossl_raise(eSSLError, "SSL_CTX_check_private_key:"); } } val = ossl_sslctx_get_client_ca(self); if(!NIL_P(val)){ if(TYPE(val) == T_ARRAY){ for(i = 0; i < RARRAY_LEN(val); i++){ client_ca = GetX509CertPtr(RARRAY_PTR(val)[i]); if (!SSL_CTX_add_client_CA(ctx, client_ca)){ /* Copies X509_NAME => FREE it. */ ossl_raise(eSSLError, "SSL_CTX_add_client_CA"); } } } else{ client_ca = GetX509CertPtr(val); /* NO DUP NEEDED. */ if (!SSL_CTX_add_client_CA(ctx, client_ca)){ /* Copies X509_NAME => FREE it. */ ossl_raise(eSSLError, "SSL_CTX_add_client_CA"); } } } val = ossl_sslctx_get_ca_file(self); ca_file = NIL_P(val) ? NULL : StringValuePtr(val); val = ossl_sslctx_get_ca_path(self); ca_path = NIL_P(val) ? NULL : StringValuePtr(val); if(ca_file || ca_path){ if (!SSL_CTX_load_verify_locations(ctx, ca_file, ca_path)) rb_warning("can't set verify locations"); } val = ossl_sslctx_get_verify_mode(self); verify_mode = NIL_P(val) ? SSL_VERIFY_NONE : NUM2INT(val); SSL_CTX_set_verify(ctx, verify_mode, ossl_ssl_verify_callback); if (RTEST(ossl_sslctx_get_client_cert_cb(self))) SSL_CTX_set_client_cert_cb(ctx, ossl_client_cert_cb); val = ossl_sslctx_get_timeout(self); if(!NIL_P(val)) SSL_CTX_set_timeout(ctx, NUM2LONG(val)); val = ossl_sslctx_get_verify_dep(self); if(!NIL_P(val)) SSL_CTX_set_verify_depth(ctx, NUM2LONG(val)); val = ossl_sslctx_get_options(self); if(!NIL_P(val)) SSL_CTX_set_options(ctx, NUM2LONG(val)); rb_obj_freeze(self); val = ossl_sslctx_get_sess_id_ctx(self); if (!NIL_P(val)){ StringValue(val); if (!SSL_CTX_set_session_id_context(ctx, (unsigned char *)RSTRING_PTR(val), RSTRING_LEN(val))){ ossl_raise(eSSLError, "SSL_CTX_set_session_id_context:"); } } if (RTEST(rb_iv_get(self, "@session_get_cb"))) { SSL_CTX_sess_set_get_cb(ctx, ossl_sslctx_session_get_cb); OSSL_Debug("SSL SESSION get callback added"); } if (RTEST(rb_iv_get(self, "@session_new_cb"))) { SSL_CTX_sess_set_new_cb(ctx, ossl_sslctx_session_new_cb); OSSL_Debug("SSL SESSION new callback added"); } if (RTEST(rb_iv_get(self, "@session_remove_cb"))) { SSL_CTX_sess_set_remove_cb(ctx, ossl_sslctx_session_remove_cb); OSSL_Debug("SSL SESSION remove callback added"); } #ifdef HAVE_SSL_SET_TLSEXT_HOST_NAME val = rb_iv_get(self, "@servername_cb"); if (!NIL_P(val)) { SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb); OSSL_Debug("SSL TLSEXT servername callback added"); } #endif return Qtrue; }